Гость
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Какой запрос лучше? first vs rownum / 13 сообщений из 13, страница 1 из 1
18.08.2019, 20:25
    #39850857
delphinotes
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Какой запрос лучше? first vs rownum
Допустим есть такой запрос:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
select min(ename) ename
  into :l_result
  from (
        select ename
          from scott.emp t
         where t.deptno = 20
         order by t.hiredate, t.empno
       )
 where rownum = 1


который используется в pl/sql-процедуре (into).
Суть задачи - вытащить первое значение из результата, удовлетворяющему некоторому условию (where t.deptno = 20), но не рандомное, а по приоритетам (order by).
Агрегатная функция min используется, чтобы вернуть NULL, если подзапрос не вернёт ни одной записи (ну т.е. чтобы не писать exception-блок).

А вот аналог с использованием аналитической функции min:
Код: plsql
1.
2.
3.
4.
select min(ename) keep(dense_rank first order by t.hiredate, t.empno) ename
  into :l_result
  from scott.emp t
 where t.deptno = 20



План выполнения первого:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
----------------------------------------------------------------------------
| Id  | Operation                  | Name | Rows | Bytes | Cost | Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT           |      |    1 |     7 |    4 | 00:00:01 |
|   1 |   SORT AGGREGATE           |      |    1 |     7 |      |          |
| * 2 |    COUNT STOPKEY           |      |      |       |      |          |
|   3 |     VIEW                   |      |    5 |    35 |    4 | 00:00:01 |
| * 4 |      SORT ORDER BY STOPKEY |      |    5 |   105 |    4 | 00:00:01 |
| * 5 |       TABLE ACCESS FULL    | EMP  |    5 |   105 |    3 | 00:00:01 |
----------------------------------------------------------------------------

Predicate Information (identified by operation id):
------------------------------------------
* 2 - filter(ROWNUM=1)
* 4 - filter(ROWNUM=1)
* 5 - filter("T"."DEPTNO"=20)



План второго:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
----------------------------------------------------------------------
| Id  | Operation            | Name | Rows | Bytes | Cost | Time     |
----------------------------------------------------------------------
|   0 | SELECT STATEMENT     |      |    1 |    21 |    3 | 00:00:01 |
|   1 |   SORT AGGREGATE     |      |    1 |    21 |      |          |
| * 2 |    TABLE ACCESS FULL | EMP  |    5 |   105 |    3 | 00:00:01 |
----------------------------------------------------------------------

Predicate Information (identified by operation id):
------------------------------------------
* 2 - filter("T"."DEPTNO"=20)




Казалось бы, второй вариант более выгодный.
И он выглядит элегантнее (если выбирается не более одного столбца).
Однако многократный прогон процедуры в цикле показывает, что первый вариант на копейку, но быстрее.
(гонял на Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production)


Есть ли какие-то весомые аргументы в пользу второго варианта?
...
Рейтинг: 0 / 0
19.08.2019, 01:26
    #39850880
Sayan Malakshinov
Модератор форума
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Какой запрос лучше? first vs rownum
delphinotes,

21757716
А вообще забей и оставь второй вариант:
1. Простой и интуитивно понятный, т.е. легкосопровождаемый
2. Более стабильный (не так зависит от различных оптимизаций)
...
Рейтинг: 0 / 0
19.08.2019, 07:19
    #39850898
delphinotes
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Какой запрос лучше? first vs rownum
xtender,

спасибо. На свежую голову походил по ссылкам, погуглил... для своей задачи увидел, что стоит сделать соответствующий индекс, а также нарисовался третий вариант с row_number:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
select min(ename) ename
--into :l_result
  from (
        select ename,
               row_number() over(order by t.hiredate, t.empno) rn
          from scott.emp t
         where t.deptno = 20
       )
 where rn = 1



план которого:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
-----------------------------------------------------------------------------
| Id  | Operation                   | Name | Rows | Bytes | Cost | Time     |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |      |    1 |    20 |    4 | 00:00:01 |
|   1 |   SORT AGGREGATE            |      |    1 |    20 |      |          |
| * 2 |    VIEW                     |      |    5 |   100 |    4 | 00:00:01 |
| * 3 |     WINDOW SORT PUSHED RANK |      |    5 |   105 |    4 | 00:00:01 |
| * 4 |      TABLE ACCESS FULL      | EMP  |    5 |   105 |    3 | 00:00:01 |
-----------------------------------------------------------------------------

Predicate Information (identified by operation id):
------------------------------------------
* 2 - filter("RN"=1)
* 3 - filter(ROW_NUMBER() OVER ( ORDER BY "T"."HIREDATE","T"."EMPNO")<=1)
* 4 - filter("T"."DEPTNO"=20)



почти такой же, как и в первом варианте.

И работает с такой же скоростью, как и первый вариант. И будет выглядеть не громоздко, если надо выбрать несколько столбцов.

(есть и четвёртый вариант с first row, но для Oracle 12)
...
Рейтинг: 0 / 0
19.08.2019, 07:31
    #39850900
-2-
-2-
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Какой запрос лучше? first vs rownum
delphinotesсделать соответствующий индексАга. Для пущей показательности в планах по таблице emp только индекса не хватает.
...
Рейтинг: 0 / 0
19.08.2019, 13:57
    #39851106
Vint
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Какой запрос лучше? first vs rownum
delphinotes,
оба варианта не очень....
попробуй
for cc in c loop
v:= cc.asd;
exit;
end loop;
и проверь по скорости на миллионе итераций. очень полезно бывает)
...
Рейтинг: 0 / 0
19.08.2019, 14:36
    #39851132
iOracleDev
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Какой запрос лучше? first vs rownum
delphinotesДопустим есть такой запрос:
Серебряной пули нет.
...
Рейтинг: 0 / 0
19.08.2019, 14:42
    #39851138
Stax
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Какой запрос лучше? first vs rownum
Vintdelphinotes,
оба варианта не очень....
попробуй
for cc in c loop
v:= cc.asd;
exit;
end loop;
и проверь по скорости на миллионе итераций. очень полезно бывает)

говорят что в новых версиях for может "подчитать" за раз/сразу множество строк (аля форалл)

.....
stax
...
Рейтинг: 0 / 0
19.08.2019, 14:52
    #39851142
Vint
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Какой запрос лучше? first vs rownum
Stax,
так он всегда читал по 100 строк, нет?
но советую проверить производительность. аналитика и группировка очень дорогие операции. сортировка и чтение сильно дешевле. по крайней мере было на 11.2 и 12.2
...
Рейтинг: 0 / 0
19.08.2019, 15:04
    #39851149
iOracleDev
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Какой запрос лучше? first vs rownum
Vintdelphinotes,
оба варианта не очень....
попробуй
for cc in c loop
v:= cc.asd;
exit;
end loop;
и проверь по скорости на миллионе итераций. очень полезно бывает)
Откуда миллион итераций? Подтягивать какие то значения в дополнение к основному запросу в цикле на миллион итераций, решение прямо скажем не очень, не лучше ли написать один запрос?
...
Рейтинг: 0 / 0
19.08.2019, 15:06
    #39851150
Sayan Malakshinov
Модератор форума
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Какой запрос лучше? first vs rownum
Хмъ, ну как бы конкретно в данном случае за вариант с keep() будут и бритва оккама, и правило большого пальца, и кисс...


Vintаналитика и группировка очень дорогие операции. сортировка и чтение сильно дешевле. по крайней мере было на 11.2 и 12.2зависит от... очень зависит... что предыдущий приведенный мной линк уже показал
...
Рейтинг: 0 / 0
19.08.2019, 15:17
    #39851161
-2-
-2-
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Какой запрос лучше? first vs rownum
Vintтак он всегда читал по 100 строк, нет?В старых версиях for читал по одной строке. Обратное от "старый" - Stax почти не наврал в сравнительных прилагательных. Где-то в 11.1 попадал на пару багов этой оптимизации, предположу это и есть первый релиз.

Vintаналитика и группировка очень дорогие операции. сортировка и чтение сильно дешевле.Группировка и аналитика суть есть сортировка, но благодаря stop key/push rank требуют меньше памяти.
...
Рейтинг: 0 / 0
19.08.2019, 15:19
    #39851162
andrey_anonymous
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Какой запрос лучше? first vs rownum
Vintтак он всегда читал по 100 строк, нет?
Нет.
Если склероз мне не изменяет, то где-то в 10 или 11 обычный for-loop научили фетчить по 5 строк на дефолтном уровне оптимизации PL/SQL.
По крайней мере в 10046 было видно "по 5".
Дальше не следил :)
...
Рейтинг: 0 / 0
19.08.2019, 15:20
    #39851166
andrey_anonymous
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Какой запрос лучше? first vs rownum
-2-Группировка и аналитика суть есть сортировка
Мнэээ... Полуэкт.
...
Рейтинг: 0 / 0
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Какой запрос лучше? first vs rownum / 13 сообщений из 13, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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