Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Векторные запросы. Оракл и все остальные СУБД


Страницы:   1 2 3

ANB ©   (2008-02-08 12:48:00) 

В честь пятницу разомнем мозги ?
Классическая задача на векторные запросы.
Часто задают и частенько решения частные.
Имеем
Table1
(
 ID,
 F1,
 F2,
 F3,
 F4
)
и
Table2
(
 ID,
 F5,
 F6,
 F7,
 F8
)
Задача - выбрать все записи из Table1 и по одной, ей соответсвующей в Table2.
Если бы Table1 ссылалась на Table2 многие к одному - лефт джойн и полное счастье.
Однако проблема наоборот.
Добавляем в Table2 поле ID_Table1 (и соответствующий FK). Связка многие к одному.

Нужно - вытащить все записи из Table1 и все поля Table2, привязанные к таблице1, но только по одной записи (которая в группе имеет самое большое поле F5).

Кто как это делает в разных субд ?


ANB   (2008-02-14 13:34:00) [1]


> укажите, пожалуйста, номер Вашего поста в этой ветке, с
> пояснением про сортировку

да мне не лень еще раз написать.

В подчиненной таблице Т2 данные сортируются по ИД_Т1, Ф5, Ф6, Ф7, ИД.

И вот по этому набору полей надо искать последнюю в группе по ИД_Т1.


> через аналитику будет гарантированно дольше

Практически так же как с агрегатными функциями. А если полей сортировки больше одного, то агрегатом вообще задерешься делать.


Кщд   (2008-02-14 09:26:00) [2]

>В оракле через аналитику попроще выходит
через аналитику будет гарантированно дольше


Кщд   (2008-02-14 09:25:00) [3]

>ANB   (13.02.08 09:32) [39]
укажите, пожалуйста, номер Вашего поста в этой ветке, с пояснением про сортировку
видимо, я Вас неверно понял


ANB   (2008-02-14 09:08:00) [4]


> ответ ориентирован на первоначальную постановку задачи)
> включить в него частные случае (типа сортировки и т.п.)
>

как раз частный случай, если сортировка идет по одному полю, легко разруливается агрегатными функциями. Попробуй модифицировать свой запрос, чтобы сортировка шла по 2-м полям.
В оракле через аналитику попроще выходит - всего 2 обращения к таблице и плюс завсегда можно настроить использование индексов. Да и распараллеленному фуллскану не помешает.


Кщд   (2008-02-13 14:54:00) [5]

>ANB   (13.02.08 14:30) [46]
ответ ориентирован на первоначальную постановку задачи)
включить в него частные случае (типа сортировки и т.п.) легко без существенного ущерба производительности
и, собственно, применим как минимум на MS SQL, Oracle & FB


ANB   (2008-02-13 14:30:00) [6]


> Кщд   (13.02.08 13:56) [45]

Ну и плюс сортировка по 2-м полям не учтена.
Это частное решение. Таким я тоже пользуюсь.

> А "фича" дублей не дает?

Когда это ИН дублил записи ? Его всегда и юзают, чтобы дублей не было
select * from T where ID in (2,2,2,2,2) - вернет всегда одну запись.


Кщд   (2008-02-13 13:56:00) [7]

>ANB   (13.02.08 11:19) [43]
>3 обращения к Т2. Мона обойтись двумя.
обращения не к таблице, но строго к индексу
необходимы для повышения производительности

>А вот это :
>and it2.f5 = (select max(it3.f5)
>не будет толком работать, если есть дубли Ф5.
работать будет, т.к. rownum

могу выложить скрипты на создание таблиц/индексов
у меня при мощности в 45млн на T2 запрос работает 5-10 секунд


Johnmen   (2008-02-13 12:22:00) [8]


> ANB   (13.02.08 11:19) [43]
> Соединение иногда может дать дубли,

Что за дубли?
А "фича" дублей не дает?

ЗЫ
У меня такое ощущение, что в изучении SQL ты свернул на какую-то боковую дорожку...:)
И при этом тебе кажется, что она основная.


ANB   (2008-02-13 11:19:00) [9]


> Кщд   (13.02.08 10:30) [42]

3 обращения к Т2. Мона обойтись двумя.
А вот это :
and it2.f5 = (select max(it3.f5)
не будет толком работать, если есть дубли Ф5.


> Johnmen ©   (13.02.08 09:57) [41]

Соединение иногда может дать дубли, от которых придется избавляться группировкой, что тоже не шустро.


Кщд   (2008-02-13 10:30:00) [10]

если так

select /*+ use_nl(t1 t2) no_merge(t2) push_pred(t2) index(t1 pk_t1)*/ t1.*, t2.*
from t1 t1
      join
      (
      select /*+ index(it i_t2$id_t1_id) */it.*
           from t2 it            
           where it.id = (
                         select it2.id
                         from t2 it2
                         where it2.t1_id = it.t1_id
                               and it2.f5 = (select max(it3.f5)
                                            from t2 it3
                                            where it3.t1_id = it.t1_id
                                                 
                                            )
                               and rownum < 2
                          )
           ) t2
        on t1.id = t2.t1_id


Johnmen   (2008-02-13 09:57:00) [11]


> А недавно накопал фичу :select * from T2 where (Т1_ИД_1,
>  Т1_ИД_2) in (select ИД_1, ИД_2 from T1).

Эта "фича" на порядок медленнее, чем соединение.
Т.е. налицо твой регресс :)


ANB   (2008-02-13 09:44:00) [12]

Откуда взялся вопрос :
Пример :
имеем Т1 и Т2. У Т1 - составной ПК по ИД_1 и ИД_2. Т2 ссылается на Т1 полями Т1_ИД_1 и Т1_ИД_2.
Надо : вытащить ином(часто бывает нужно) записи из Т2 по определенному набору записей в Т1. Раньше чесал репу и таки обычно джойнил. А недавно накопал фичу :
select * from T2 where (Т1_ИД_1, Т1_ИД_2) in (select ИД_1, ИД_2 from T1).
Удобно. Аналогичная фича нашлась и для update - когда надо обновить набор полей из одной записи другой таблицы.
update T1
set (F1, F2, F3) = (select F1, F2, F3 from T2).

Причем фичу накопал в книжке для чайников. Абыдно.

Вот я и интерисуюсь - а нету ли какой нибудь фичи для облегчения векторных запросов. Аналитика помогает, но не очень.

ЗЫ. Век живи век учись.


ANB   (2008-02-13 09:32:00) [13]


> ты б изначальную задачу привел, а то фиг поймешь, что же
> надо

Задача теоретическая : накопать самый удобный способ для векторных запросов. На практике проблема решается кажный раз по разному.


ANB   (2008-02-13 09:30:00) [14]


> план Вашего запроса можно увидеть?

SELECT STATEMENT, GOAL = CHOOSE   Cost=6 Cardinality=3 Bytes=1011
NESTED LOOPS OUTER   Cost=6 Cardinality=3 Bytes=1011
 NESTED LOOPS   Cost=5 Cardinality=3 Bytes=834
  VIEW Object owner=QUORUM  Cost=4 Cardinality=3 Bytes=57
   SORT GROUP BY   Cost=4 Cardinality=3 Bytes=135
    NESTED LOOPS OUTER   Cost=2 Cardinality=5 Bytes=225
     INLIST ITERATOR    
      INDEX RANGE SCAN Object owner=QUORUM Object name=CNUM Cost=1 Cardinality=3 Bytes=30
     TABLE ACCESS BY INDEX ROWID Object owner=QUORUM Object name=CRLIM Cost=1 Cardinality=2 Bytes=70
      INDEX RANGE SCAN Object owner=QUORUM Object name=CRLIM4 Cost=1 Cardinality=1
  TABLE ACCESS BY INDEX ROWID Object owner=QUORUM Object name=CREDCONT Cost=1 Cardinality=1 Bytes=259
   INDEX UNIQUE SCAN Object owner=QUORUM Object name=CNUM  Cardinality=1
 TABLE ACCESS BY INDEX ROWID Object owner=QUORUM Object name=CRLIM Cost=1 Cardinality=1 Bytes=59
  INDEX UNIQUE SCAN Object owner=QUORUM Object name=AD_CRLIM  Cardinality=1


Petr V. Abramov   (2008-02-12 22:37:00) [15]

> ANB
ты б изначальную задачу привел, а то фиг поймешь, что же надо


Кщд   (2008-02-12 18:35:00) [16]

>ANB   (11.02.08 16:06) [13]
конечно, будет - сами понимаете - group by)
план Вашего запроса можно увидеть?


ANB   (2008-02-12 18:03:00) [17]


> Что такое "быстро" и что такое "медленно"? Какие у тебя
> координаты для измерения? Относительно чего?

Имеем запись в Т1. Имеем 200 000 подчиненных ейзаписей в Т2, из которых отобрать надо одну ("последнюю" с точки зрения пользователя). Ну и в Т1 записей штук 5 000 (каждой из которых подчинено от 10 000 до 200 000 записей в Т2). В таких условиях использование индекса по "естественному" ключу в Т2 становится сильно полезным.


Johnmen   (2008-02-12 17:34:00) [18]


> а вот отбор нужной единственной будет идти перебором.
> И тут уж - если записей мало, то быстро. Иначе - медленно.

Что такое "быстро" и что такое "медленно"? Какие у тебя координаты для измерения? Относительно чего?

>  Впрочем, я ща попробую - прикрутится индекс или нет.

Да что ты зациклился на индексе?! Религия что-ли?
:))


ANB   (2008-02-12 17:23:00) [19]

Вдогонку : я говорил не о том, что получим вредный фулл-скан. А о том, что я не смогу запустить полезный фулл скан из-за использования функции.


ANB   (2008-02-12 17:21:00) [20]


> М-дя...
> Вообще-то соединение это чуть повыше, первое условие в where.
>
> М.б. стОит подчитать теорию?

Значит можно будет по индексу отсечь подчиненные записи в Т2, а вот отбор нужной единственной будет идти перебором. И тут уж - если записей мало, то быстро. Иначе - медленно. Впрочем, я ща попробую - прикрутится индекс или нет.


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо