Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Помогите с оптимизацией запроса / 8 сообщений из 8, страница 1 из 1
26.09.2018, 07:04
    #39708125
alx71
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с оптимизацией запроса
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
create table t1
(
id number(12) primary key t1_pk
)
;

create table t2
(
id number(12) foreign key t2_fk references t1(id)
)
;
create index t2_id_i on t2(id);



Необходимо для каждой записи из t1 выбрать не более 10 записей из t2 по условию t1.id=t2.id

Код: plsql
1.
2.
3.
4.
5.
select * from
(
  select t1.id,t2.id,row_number() over (partition by t1.id order by t1.id) rn from t1,t2 where t1.id=t2.id
) where rn <= 10
;



Проблема в том, что такой запрос приводит к index full scan по t2. FIRST_ROWS не помогает.

Можно ли оптимизировать?
...
Рейтинг: 0 / 0
26.09.2018, 07:35
    #39708134
Щукина Анна
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с оптимизацией запроса
alx71,

Ваша хотелка хорошо бы легла на механизмы [[CROSS | OUTER] APPLY | LATERAL] джойнов в паре с TOP-N запросами (OFFSET FETCH N FIRST | LAST ROWS ONLY).
Но такое официально доступно лишь с версии 12с.

З.Ы.
Небольшими хитростями можно заставить работать LATER на версии 11g. Логику топ-n запросов придется городить по старинке - через ROWNUM
...
Рейтинг: 0 / 0
26.09.2018, 09:19
    #39708167
Stax
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с оптимизацией запроса
Щукина Анна,

можете привести пример с TOP-N для случая partition by t1.id в 12-ке

.....
stax
...
Рейтинг: 0 / 0
26.09.2018, 09:25
    #39708170
-2-
-2-
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с оптимизацией запроса
alx71Необходимо для каждой записи из t1 выбрать не более 10 записей из t2 по условию t1.id=t2.id

Код: plsql
1.
2.
3.
4.
5.
select * from
(
  select t1.id,t2.id,row_number() over (partition by t1.id order by t1.id) rn from t1,t2 where t1.id=t2.id
) where rn <= 10
;

Код: plsql
1.
2.
3.
4.
select * from
(
  select t2.id,t2.id,row_number() over (partition by t2.id order by t2.id) rn from t2
) where rn <= 10;
...
Рейтинг: 0 / 0
26.09.2018, 09:48
    #39708190
alx71
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с оптимизацией запроса
-2-, я упростил свою ситуацию. IRL t1 выбрасывать нельзя.
...
Рейтинг: 0 / 0
26.09.2018, 10:33
    #39708231
-2-
-2-
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с оптимизацией запроса
alx71я упростил свою ситуацию.А я упростил свою оптимизацию.
...
Рейтинг: 0 / 0
26.09.2018, 10:34
    #39708234
MaximaXXL
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с оптимизацией запроса
alx71,

Селект ОЧЕНЬ упрощен, и я не уверен что он в ТАКОМ виде тоже работает по full scan.

А так, попробуйте хинтами прибить
https://docs.oracle.com/cd/B12037_01/server.101/b10752/hintsref.htm
или покажите оригинальный селект
...
Рейтинг: 0 / 0
26.09.2018, 18:51
    #39708758
Щукина Анна
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с оптимизацией запроса
StaxЩукина Анна,

можете привести пример с TOP-N для случая partition by t1.id в 12-ке

.....
stax
Oracle 12c под рукой нет, покажу на скульсервере.
Тестовые данные - немного отличается по синтаксису от оракла,
но основная часть запроса, в том числе OUTER APPLY подзапрос (?) и OFFSET / FETCH - в точности соответствуют оракловым, ибо - стандарт ANSI ;)

запрос, проверка на скульфидле: http://sqlfiddle.com/#!18/9eecb/34913
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
-- Тестовые данные:
with
-- Первая таблица, на три строчки:
t1 (id) as 
    (
      select * from (values
                       (1)
                      ,(2)
                      ,(3)
                    ) v(id)
    )
-- Вторая таблица, для каждой записи из t1 в ней есть по 5 записей с разными значениями f
,t2 (id_t1, f) as
    (
      select * from (values
                       (1,1)
                      ,(1,2)
                      ,(1,3)
                      ,(1,4)
                      ,(1,5)
                      ,(2,1)
                      ,(2,2)
                      ,(2,3)
                      ,(2,4)
                      ,(2,5)
                      ,(3,1)
                      ,(3,2)
                      ,(3,3)
                      ,(3,4)
                      ,(3,5)
                    )v(id_t1, f))
-- Основной запрос:
select t1.id, cav.f 
  from t1
 cross apply -- Доступно с версии Oracle 12c
   (
     select f 
       from t2
      where t2.id_t1 = t1.id
-- Для каждой записи из t1 выбираем по три первых строки, в сортировке по f:
-- (по сути - аналог row_number() over(partition by t1.id order by t2.f) <= 3)
     order by t2.f
     offset 0 rows            -- Доступно с версии Oracle 12c
      fetch next 3 rows only  -- Доступно с версии Oracle 12c
   ) cav

...
Рейтинг: 0 / 0
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Помогите с оптимизацией запроса / 8 сообщений из 8, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]