powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Блеск и нищета оконных функций в ФБ
1 сообщений из 1, страница 1 из 1
Блеск и нищета оконных функций в ФБ
    #38606270
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hi all

... в продолжение нескольких прошлых топегов про over()-инструменты.

LI-T3.0.0.31003, SuperServer.

Код: plaintext
1.
2.
3.
recreate table td(id int primary key, pid int , s01 varchar(16) ); commit;
insert into td select row_number()over(), 1+rand()*49999, left(uuid_to_char(gen_uuid()),16)
from rdb$types,rdb$types,rdb$types rows 1000000;
commit;

Итого: число разных pid не превышает 50 тыс, всего же - 1 млн записей.
Допустим, требуется найти для каждого pid такое значение поля s01, которое соотв-вует максимальному id для этого pid. Эту задачу спрашивал недавно товарищ "ТРАКТОРА", но она вообще частая гостья.
(пользуясь случаем, должен принести пардон Трактору: я там привел запрос с неверным результатом, нужно было учесть, что каст чисел к char(11) и их сортировка будут идти по алфавиту, а не по возрастанию значений :); фикс очевиден - см ниже)


Смотрим, что будет со статистикой для следующих трёх вариантов.

var-1. Без употребления over()-функций:
Код: sql
1.
select d.pid, substring( max( cast( 10000000000 + id as char(11)) || d.s01 ) from 12) s from td d group by 1

Трейс для трёх запусков:
~2960 ms
Код: plaintext
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.
46.
47.
48.
49.
2014-04-06T01:41:51.3740 (6403:0x7f309ceda100) EXECUTE_STATEMENT_FINISH
        sqlex30 (ATT_397, SYSDBA:NONE, NONE, TCPv4:127.0.0.1)
        /opt/fb30trnk/bin/isql:361
                (TRA_12801, CONCURRENCY | WAIT | READ_WRITE)

Statement 107:
-------------------------------------------------------------------------------
select d.pid, substring( max( cast( 10000000000 + id as char(11)) || d.s01 ) from 12) s from td d group by 1
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PLAN SORT (D NATURAL)
50000 records fetched
   2962 ms, 18108 read(s), 2036385 fetch(es)

Table                             Natural     Index    Update    Insert    Delete   Backout     Purge   Expunge
***************************************************************************************************************
TD                                1000000                                                                     

2014-04-06T01:41:56.0120 (6403:0x7f309ceda100) EXECUTE_STATEMENT_FINISH
        sqlex30 (ATT_397, SYSDBA:NONE, NONE, TCPv4:127.0.0.1)
        /opt/fb30trnk/bin/isql:361
                (TRA_12801, CONCURRENCY | WAIT | READ_WRITE)

Statement 108:
-------------------------------------------------------------------------------
select d.pid, substring( max( cast( 10000000000 + id as char(11)) || d.s01 ) from 12) s from td d group by 1
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PLAN SORT (D NATURAL)
50000 records fetched
   2964 ms, 18200 read(s), 2036385 fetch(es)

Table                             Natural     Index    Update    Insert    Delete   Backout     Purge   Expunge
***************************************************************************************************************
TD                                1000000                                                                     

2014-04-06T01:42:00.2280 (6403:0x7f309ceda100) EXECUTE_STATEMENT_FINISH
        sqlex30 (ATT_397, SYSDBA:NONE, NONE, TCPv4:127.0.0.1)
        /opt/fb30trnk/bin/isql:361
                (TRA_12801, CONCURRENCY | WAIT | READ_WRITE)

Statement 109:
-------------------------------------------------------------------------------
select d.pid, substring( max( cast( 10000000000 + id as char(11)) || d.s01 ) from 12) s from td d group by 1
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PLAN SORT (D NATURAL)
50000 records fetched
   2961 ms, 18200 read(s), 2036385 fetch(es)

Table                             Natural     Index    Update    Insert    Delete   Backout     Purge   Expunge
***************************************************************************************************************
TD                                1000000                      
План и статистика в isql:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
Select Expression
    -> Aggregate
        -> Sort ( record length: 96 , key length: 8)
            -> Table "D" Full Scan
Current memory = 12766584
Delta memory = 0
Max memory = 788968768
Elapsed time= 3.044 sec
Cpu = 0.150 sec
Buffers = 2048
Reads = 18218
Writes = 0
Fetches = 2036407


var-2. С использованием max()over(), без group by:
Код: sql
1.
select pid, s from ( select d.pid, d.id,  max(id)over(partition by pid) m, s01 s from td d  ) where id=m

Trace:
~4530 ms
Код: plaintext
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.
46.
47.
48.
49.
2014-04-06T01:46:04.9040 (6403:0x7f309ceda100) EXECUTE_STATEMENT_FINISH
        sqlex30 (ATT_397, SYSDBA:NONE, NONE, TCPv4:127.0.0.1)
        /opt/fb30trnk/bin/isql:361
                (TRA_12801, CONCURRENCY | WAIT | READ_WRITE)

Statement 110:
-------------------------------------------------------------------------------
select pid, s from ( select d.pid, d.id,  max(id)over(partition by pid) m, s01 s from td d  ) where id=m
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PLAN SORT (D NATURAL)
50000 records fetched
   4528 ms, 18200 read(s), 2036385 fetch(es)

Table                             Natural     Index    Update    Insert    Delete   Backout     Purge   Expunge
***************************************************************************************************************
TD                                1000000                                                                     

2014-04-06T01:46:12.1840 (6403:0x7f309ceda100) EXECUTE_STATEMENT_FINISH
        sqlex30 (ATT_397, SYSDBA:NONE, NONE, TCPv4:127.0.0.1)
        /opt/fb30trnk/bin/isql:361
                (TRA_12801, CONCURRENCY | WAIT | READ_WRITE)

Statement 111:
-------------------------------------------------------------------------------
select pid, s from ( select d.pid, d.id,  max(id)over(partition by pid) m, s01 s from td d  ) where id=m
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PLAN SORT (D NATURAL)
50000 records fetched
   4528 ms, 18200 read(s), 2036385 fetch(es)

Table                             Natural     Index    Update    Insert    Delete   Backout     Purge   Expunge
***************************************************************************************************************
TD                                1000000                                                                     

2014-04-06T01:46:17.7220 (6403:0x7f309ceda100) EXECUTE_STATEMENT_FINISH
        sqlex30 (ATT_397, SYSDBA:NONE, NONE, TCPv4:127.0.0.1)
        /opt/fb30trnk/bin/isql:361
                (TRA_12801, CONCURRENCY | WAIT | READ_WRITE)

Statement 112:
-------------------------------------------------------------------------------
select pid, s from ( select d.pid, d.id,  max(id)over(partition by pid) m, s01 s from td d  ) where id=m
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PLAN SORT (D NATURAL)
50000 records fetched
   4531 ms, 18200 read(s), 2036385 fetch(es)

Table                             Natural     Index    Update    Insert    Delete   Backout     Purge   Expunge
***************************************************************************************************************
TD                                1000000                                
isql:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
Select Expression
    -> Filter
        -> Window
            -> Record Buffer (record length: 193)
                -> Sort ( record length: 188 , key length: 8)
                    -> Window
                        -> Record Buffer (record length: 97)
                            -> Table "D" Full Scan
Current memory = 12747264
Delta memory = 0
Max memory = 788968768
Elapsed time= 4.595 sec
Cpu = 0.150 sec
Buffers = 2048
Reads = 18217
Writes = 0
Fetches = 2036406
Время сильно больше. Не связано ли это с record len, которая здесь 188, а в первом варианте - 96 ?

var-3. Через dense_rank() вместо предыдущего max()over():
Код: sql
1.
select pid, s from (select d.pid, dense_rank()over(partition by pid order by id desc) r, s01 s from td d) where r=1

Trace:
~4750 ms
Код: plaintext
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.
46.
47.
48.
49.
2014-04-06T01:51:08.0030 (6403:0x7f309ceda100) EXECUTE_STATEMENT_FINISH
        sqlex30 (ATT_397, SYSDBA:NONE, NONE, TCPv4:127.0.0.1)
        /opt/fb30trnk/bin/isql:361
                (TRA_12801, CONCURRENCY | WAIT | READ_WRITE)

Statement 113:
-------------------------------------------------------------------------------
select pid, s from (select d.pid, dense_rank()over(partition by pid order by id desc) r, s01 s from td d) where r=1
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PLAN SORT (D NATURAL)
50000 records fetched
   4754 ms, 18200 read(s), 2036385 fetch(es)

Table                             Natural     Index    Update    Insert    Delete   Backout     Purge   Expunge
***************************************************************************************************************
TD                                1000000                                                                     

2014-04-06T01:51:20.6540 (6403:0x7f309ceda100) EXECUTE_STATEMENT_FINISH
        sqlex30 (ATT_397, SYSDBA:NONE, NONE, TCPv4:127.0.0.1)
        /opt/fb30trnk/bin/isql:361
                (TRA_12801, CONCURRENCY | WAIT | READ_WRITE)

Statement 114:
-------------------------------------------------------------------------------
select pid, s from (select d.pid, dense_rank()over(partition by pid order by id desc) r, s01 s from td d) where r=1
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PLAN SORT (D NATURAL)
50000 records fetched
   4742 ms, 18200 read(s), 2036385 fetch(es)

Table                             Natural     Index    Update    Insert    Delete   Backout     Purge   Expunge
***************************************************************************************************************
TD                                1000000                                                                     

2014-04-06T01:51:27.0950 (6403:0x7f309ceda100) EXECUTE_STATEMENT_FINISH
        sqlex30 (ATT_397, SYSDBA:NONE, NONE, TCPv4:127.0.0.1)
        /opt/fb30trnk/bin/isql:361
                (TRA_12801, CONCURRENCY | WAIT | READ_WRITE)

Statement 115:
-------------------------------------------------------------------------------
select pid, s from (select d.pid, dense_rank()over(partition by pid order by id desc) r, s01 s from td d) where r=1
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PLAN SORT (D NATURAL)
50000 records fetched
   4760 ms, 18200 read(s), 2036385 fetch(es)

Table                             Natural     Index    Update    Insert    Delete   Backout     Purge   Expunge
***************************************************************************************************************
TD                                1000000      
isql:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
Select Expression
    -> Filter
        -> Window
            -> Record Buffer (record length: 185)
                -> Sort (record length: 188, key length: 16)
                    -> Window
                        -> Record Buffer (record length: 97)
                            -> Table "D" Full Scan
Current memory = 12745256
Delta memory = 0
Max memory = 788968768
Elapsed time= 4.825 sec
Cpu = 0.160 sec
Buffers = 2048
Reads = 18217
Writes = 0
Fetches = 2036406


Я не понимаю, отчего второй вариант так сильно проигрывает первому. Печалько, что не видно ни фига, сколько затрат на себя берёт та или иная операция в extended-plan'e.

И также интересно зело, почему третий вариант отстаёт от второго (ненамного, но это я вижу устойчиво).

ЗЫ. Да, понятно, что для случая, показанного недавно Денисом, со "знакопеременными" сортировка в одном запросе:
Код: sql
1.
2.
select min( x )over(partition by y order by z asc), max( y )over(partition by x order by z desc)
from ...

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


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