powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / оптимизация limit по union all (когда лимит нельзя перенести в подзапрос)
25 сообщений из 35, страница 1 из 2
оптимизация limit по union all (когда лимит нельзя перенести в подзапрос)
    #39520028
Фотография Legushka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
размышления

есть подзапрос: объедены две выборки через union all
набор строк в подзапросе может достигать нескольких сотен тыс

на общий результат накладывается еще куча джоинов не увеличивающих и не уменьшающих общее количество row

нет возможности лимит и оффсет перенести в подзапрос, (к сожалению используемый движок не позволяет, limit всегда в конце запроса)

есть общая сортировка по дате (дата определяется в обоих частях подзапроса, но из разных источников)

лимитом отбирается стабильно максимум 10 строк, все зависит от пагинации

Можно ли в этом случае ускорить пагинацию, что бы не собирать все строки, или в текущем варианте бесполезно?
...
Рейтинг: 0 / 0
оптимизация limit по union all (когда лимит нельзя перенести в подзапрос)
    #39520035
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Legushka,

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

даже хуже -- добавляшь в ордер бай в конец уникализирующее поле -- и все с ис с лимитом вдоль скатывается в лимит после сорта всего (всего !) , блин, скана.

всё в ваших руках
...
Рейтинг: 0 / 0
оптимизация limit по union all (когда лимит нельзя перенести в подзапрос)
    #39520040
Фотография Legushka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
qwwq,
а есть какие нибудь методы как решить? в голову ничего не приходит
не хочется ковырять все записи что бы потом отобрать только 10
...
Рейтинг: 0 / 0
оптимизация limit по union all (когда лимит нельзя перенести в подзапрос)
    #39520066
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Legushkaqwwq,
а есть какие нибудь методы как решить? в голову ничего не приходит
не хочется ковырять все записи что бы потом отобрать только 10

писать запросы руками и вставлять limit 10 в обе части union all
насколько поможет - не факт но это единственное куда вообще можно копать.
Что там позволяет или нет ваш движек - ваши проблемы, можно всегда запрос в хранимку засунуть если очень хочется.


--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru
...
Рейтинг: 0 / 0
оптимизация limit по union all (когда лимит нельзя перенести в подзапрос)
    #39520068
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Legushka Можно ли в этом случае ускорить пагинацию, что бы не собирать все строки, или в текущем варианте бесполезно?

Если у вас еще и offset - то почти невозможно почти, хотя если Limit+offset обычно небольшие (т.е. ходят на первые страницы) то можно сделать финт ушами вида

select * from
(select ...
LIMIT [offset+limit]
) UNION ALL
(select ...
LIMIT [offset+limit]
)
ORDER BY ...
OFFSET offset
LIMIT limit;

PS: в приличных местах за неограниченный (т.е не первые 5-10 страниц) paging через limit/offset - бьют по лицу (это крайне плохо заканчивается для базы, особенно весело когда приходит какой то тупой робот и начинает через limit/offset перебирать несколько миллионов страниц последовательно).

--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru
...
Рейтинг: 0 / 0
оптимизация limit по union all (когда лимит нельзя перенести в подзапрос)
    #39520077
Фотография Legushka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Boguk , да там лимит и офсет добавляется движком,
к сожалению движок нельзя переделать что бы он лимиты в указанноое место вставлял

а что если подзапрос вида union all
как нибудь развернуть на join'ах (cross join, full outer join)
...
Рейтинг: 0 / 0
оптимизация limit по union all (когда лимит нельзя перенести в подзапрос)
    #39520085
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Legushka,

теоретиццки он может мердж--аппенд выполнить в одной связке с лимитом.
т.е. партиции при наличии во всех индексов того же порядка, что и внешний одербай к головной. (но только с точностью до буквы. взять по 10+ (Вычитать все узлы неуникального) и отресортить и опять отрезать 10 ( или (до)сортить первенца в процессе,, и обрезать вычитку из отстающих ..) -- вот это всё оно не умеет.

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

а увидеть, что внутренности юниона (шире -- аппенда) можно дёшево смёрджить с минимальным ресортом и оверфетчем, в общем случае оно не умеет.

а за пагинацию оффсетом таки руки отрывать бы надо бы. но вот всё у них так -- некому свистоперделки писать будет.
...
Рейтинг: 0 / 0
оптимизация limit по union all (когда лимит нельзя перенести в подзапрос)
    #39520088
Фотография Legushka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
глянул на разницу планов если бы лимит и офсет отработал внутри подзапроса и снаружи
уже большой выигрышь на внешних join получается (всего 10 раз вместо 100k )
буду трясти разработчиков движка что бы реализовали возможность вставки лимита в любую часть запроса)
...
Рейтинг: 0 / 0
оптимизация limit по union all (когда лимит нельзя перенести в подзапрос)
    #39520091
PgSQLanonymous3
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Legushkaглянул на разницу планов если бы лимит и офсет отработал внутри подзапроса и снаружи
уже большой выигрышь на внешних join получается (всего 10 раз вместо 100k )
буду трясти разработчиков движка что бы реализовали возможность вставки лимита в любую часть запроса)А покажите всё же пример с данными и запросом... может быть, что-то всё же можно будет сделать.
Это (LIMIT только "снаружи") у Вас единственное ограничение, кстати?
...
Рейтинг: 0 / 0
оптимизация limit по union all (когда лимит нельзя перенести в подзапрос)
    #39520270
Фотография Legushka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim BogukPS: в приличных местах за неограниченный (т.е не первые 5-10 страниц) paging через limit/offset - бьют по лицу (это крайне плохо заканчивается для базы, особенно весело когда приходит какой то тупой робот и начинает через limit/offset перебирать несколько миллионов страниц последовательно).
еще не делал пагинацию ни разу, как правильно реализовать если не через limit/offset, который присутствует в текущей версии?
...
Рейтинг: 0 / 0
оптимизация limit по union all (когда лимит нельзя перенести в подзапрос)
    #39520279
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LegushkaMaxim BogukPS: в приличных местах за неограниченный (т.е не первые 5-10 страниц) paging через limit/offset - бьют по лицу (это крайне плохо заканчивается для базы, особенно весело когда приходит какой то тупой робот и начинает через limit/offset перебирать несколько миллионов страниц последовательно).
еще не делал пагинацию ни разу, как правильно реализовать если не через limit/offset, который присутствует в текущей версии?

Ну вот например есть у вас таблица с постами в форуме. Следующая страница (ссылки) формируется не через limit/offset (которые не будут корректно работать если новые посты например появляются), а через where post_id<(последний post_id на текущей странице) LIMIT сколько вам надо.
Т.е. не ссылка на prev page вида skip=50 а ссылка на prev page вида before_post_id=[последний post_id на текущей странице].
Тогда как минимум это во многих случаях будет нормально работать по скорости и главное навигация не будет ломаться при появлении новых постов (что в 100% случаев происходит с limit/offset пагинацией).

PS: если у вас там 5-10 страниц максимум - можно и limit/offset а вот если потенциально 1000 страниц - то нет.

--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru
...
Рейтинг: 0 / 0
оптимизация limit по union all (когда лимит нельзя перенести в подзапрос)
    #39520291
Ivan Durak
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LegushkaMaxim Boguk , да там лимит и офсет добавляется движком,
к сожалению движок нельзя переделать что бы он лимиты в указанноое место вставлял

а что если подзапрос вида union all
как нибудь развернуть на join'ах (cross join, full outer join)
легко
full join + группировка и прекрасно заменяется
...
Рейтинг: 0 / 0
оптимизация limit по union all (когда лимит нельзя перенести в подзапрос)
    #39520292
Ivan Durak
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
правда сомневаюсь что это тебе помоежет. Лимит все равно до джоина применяться не будет
...
Рейтинг: 0 / 0
оптимизация limit по union all (когда лимит нельзя перенести в подзапрос)
    #39520488
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Постгрес может эффективно выполнить такой запрос - выбрав не все строки, а только нужные по лимиту. Важно, чтобы на каждой таблице существовал нужный индекс, чтобы не требовалось переупорядочивание строк. Тогда сможет использовать Merge Append, джоин по Nested Loop и Limit.


Вот пример такого боевого запроса:

EXPLAIN (ANALYZE) SELECT usage.req_begin AS usage_req_begin, usage.req_started AS usage_req_started, usage.req_max AS usage_req_max, usage.req_dur AS usage_req_dur, usage.sess_begin AS usage_sess_begin, usage.sess_started AS usage_sess_started, usage.sess_max AS usage_sess_max, usage.sess_dur AS usage_sess_dur, usage.bytes_out AS usage_bytes_out, usage.bytes_out_cached AS usage_bytes_out_cached, usage.max_interval_bytes AS usage_max_interval_bytes, time.year AS time_year, time.month AS time_month, time.day AS time_day, time.hour AS time_hour, time.minute AS time_minute, geo.country AS geo_country, geo.region AS geo_region, useragent.browser AS useragent_browser, useragent.platform AS useragent_platform, backend.torso_id AS backend_torso_id, proto.name AS proto_name, referrer.name AS referrer_name, custom.field1 AS custom_field1, status.code AS status_code, clienturi.client_id AS clienturi_client_id, clienturi.hostname AS clienturi_hostname, clienturi.uri AS clienturi_uri FROM usage INNER JOIN (VALUES (448540, 753, 4176, 210, 67, 11713775, 1, 1, 649608573)) AS ids(time_id, geo_id, useragent_id, backend_id, proto_id, referrer_id, custom_id, status_id, clienturi_parent_id) ON (usage.time_id, usage.geo_id, usage.useragent_id, usage.backend_id, usage.proto_id, usage.referrer_id, usage.custom_id, usage.status_id, usage.clienturi_parent_id) = (ids.time_id, ids.geo_id, ids.useragent_id, ids.backend_id, ids.proto_id, ids.referrer_id, ids.custom_id, ids.status_id, ids.clienturi_parent_id) CROSS JOIN LATERAL (SELECT time.* FROM time WHERE time.id = usage.time_id LIMIT 1) AS time CROSS JOIN LATERAL (SELECT geo.* FROM geo WHERE geo.id = usage.geo_id LIMIT 1) AS geo CROSS JOIN LATERAL (SELECT useragent.* FROM useragent WHERE useragent.id = usage.useragent_id LIMIT 1) AS useragent CROSS JOIN LATERAL (SELECT backend.* FROM backend WHERE backend.id = usage.backend_id LIMIT 1) AS backend CROSS JOIN LATERAL (SELECT proto.* FROM proto WHERE proto.id = usage.proto_id LIMIT 1) AS proto CROSS JOIN LATERAL (SELECT referrer.* FROM referrer WHERE referrer.id = usage.referrer_id LIMIT 1) AS referrer CROSS JOIN LATERAL (SELECT custom.* FROM custom WHERE custom.id = usage.custom_id LIMIT 1) AS custom CROSS JOIN LATERAL (SELECT status.* FROM status WHERE status.id = usage.status_id LIMIT 1) AS status CROSS JOIN LATERAL (SELECT clienturi.* FROM clienturi WHERE clienturi.id = usage.clienturi_id LIMIT 1) AS clienturi ORDER BY usage_bytes_out desc LIMIT 10

Код: 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.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
                                                                                                                                               QUERY PLAN                                                                                                                                                
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=8.30..489.06 rows=10 width=281) (actual time=0.296..0.890 rows=10 loops=1)
   ->  Nested Loop  (cost=8.30..633.29 rows=13 width=281) (actual time=0.296..0.889 rows=10 loops=1)
         ->  Nested Loop  (cost=8.30..558.59 rows=13 width=215) (actual time=0.273..0.778 rows=10 loops=1)
               ->  Nested Loop  (cost=8.30..515.82 rows=13 width=215) (actual time=0.267..0.744 rows=10 loops=1)
                     ->  Nested Loop  (cost=8.30..443.58 rows=13 width=186) (actual time=0.262..0.712 rows=10 loops=1)
                           ->  Nested Loop  (cost=8.30..370.06 rows=13 width=165) (actual time=0.244..0.646 rows=10 loops=1)
                                 ->  Nested Loop  (cost=8.30..358.32 rows=13 width=153) (actual time=0.226..0.563 rows=10 loops=1)
                                       ->  Nested Loop  (cost=8.30..330.43 rows=13 width=151) (actual time=0.189..0.347 rows=10 loops=1)
                                             ->  Nested Loop  (cost=8.30..258.27 rows=13 width=114) (actual time=0.178..0.293 rows=10 loops=1)
                                                   ->  Nested Loop  (cost=8.30..186.14 rows=13 width=90) (actual time=0.167..0.240 rows=10 loops=1)
                                                         ->  Merge Append  (cost=8.30..113.30 rows=13 width=74) (actual time=0.146..0.169 rows=10 loops=1)
                                                               Sort Key: usage.bytes_out DESC
                                                               ->  Index Scan Backward using usage_time_id_clienturi_parent_id_geo_id_useragent_id_backe_idx on usage  (cost=0.12..8.16 rows=1 width=74) (actual time=0.006..0.006 rows=0 loops=1)
                                                                     Index Cond: ((time_id = 448540) AND (clienturi_parent_id = 649608573) AND (geo_id = 753) AND (useragent_id = 4176) AND (backend_id = 210) AND (proto_id = 67) AND (referrer_id = 11713775) AND (status_id = 1) AND (custom_id = 1))
                                                               ->  Index Scan Backward using usage_2017_time_id_clienturi_parent_id_geo_id_useragent_id__idx on usage_2017  (cost=0.70..8.74 rows=1 width=74) (actual time=0.028..0.049 rows=10 loops=1)
                                                                     Index Cond: ((time_id = 448540) AND (clienturi_parent_id = 649608573) AND (geo_id = 753) AND (useragent_id = 4176) AND (backend_id = 210) AND (proto_id = 67) AND (referrer_id = 11713775) AND (status_id = 1) AND (custom_id = 1))
                                                               ->  Index Scan Backward using usage_2016_time_id_clienturi_parent_id_geo_id_useragent_id__idx on usage_2016  (cost=0.70..8.74 rows=1 width=74) (actual time=0.011..0.011 rows=0 loops=1)
                                                                     Index Cond: ((time_id = 448540) AND (clienturi_parent_id = 649608573) AND (geo_id = 753) AND (useragent_id = 4176) AND (backend_id = 210) AND (proto_id = 67) AND (referrer_id = 11713775) AND (status_id = 1) AND (custom_id = 1))
                                                               ->  Index Scan Backward using usage_2017_04_time_id_clienturi_parent_id_geo_id_useragent__idx on usage_2017_04  (cost=0.71..8.75 rows=1 width=74) (actual time=0.010..0.010 rows=0 loops=1)
                                                                     Index Cond: ((time_id = 448540) AND (clienturi_parent_id = 649608573) AND (geo_id = 753) AND (useragent_id = 4176) AND (backend_id = 210) AND (proto_id = 67) AND (referrer_id = 11713775) AND (status_id = 1) AND (custom_id = 1))
                                                               ->  Index Scan Backward using usage_2017_03_time_id_clienturi_parent_id_geo_id_useragent__idx on usage_2017_03  (cost=0.71..8.74 rows=1 width=74) (actual time=0.010..0.010 rows=0 loops=1)
                                                                     Index Cond: ((time_id = 448540) AND (clienturi_parent_id = 649608573) AND (geo_id = 753) AND (useragent_id = 4176) AND (backend_id = 210) AND (proto_id = 67) AND (referrer_id = 11713775) AND (status_id = 1) AND (custom_id = 1))
                                                               ->  Index Scan Backward using usage_2017_06_time_id_clienturi_parent_id_geo_id_useragent__idx on usage_2017_06  (cost=0.71..8.75 rows=1 width=74) (actual time=0.011..0.011 rows=0 loops=1)
                                                                     Index Cond: ((time_id = 448540) AND (clienturi_parent_id = 649608573) AND (geo_id = 753) AND (useragent_id = 4176) AND (backend_id = 210) AND (proto_id = 67) AND (referrer_id = 11713775) AND (status_id = 1) AND (custom_id = 1))
                                                               ->  Index Scan Backward using usage_2017_05_time_id_clienturi_parent_id_geo_id_useragent__idx on usage_2017_05  (cost=0.71..8.75 rows=1 width=74) (actual time=0.009..0.009 rows=0 loops=1)
                                                                     Index Cond: ((time_id = 448540) AND (clienturi_parent_id = 649608573) AND (geo_id = 753) AND (useragent_id = 4176) AND (backend_id = 210) AND (proto_id = 67) AND (referrer_id = 11713775) AND (status_id = 1) AND (custom_id = 1))
                                                               ->  Index Scan Backward using usage_2017_02_time_id_clienturi_parent_id_geo_id_useragent__idx on usage_2017_02  (cost=0.71..8.74 rows=1 width=74) (actual time=0.011..0.011 rows=0 loops=1)
                                                                     Index Cond: ((time_id = 448540) AND (clienturi_parent_id = 649608573) AND (geo_id = 753) AND (useragent_id = 4176) AND (backend_id = 210) AND (proto_id = 67) AND (referrer_id = 11713775) AND (status_id = 1) AND (custom_id = 1))
                                                               ->  Index Scan Backward using usage_2017_01_time_id_clienturi_parent_id_geo_id_useragent__idx on usage_2017_01  (cost=0.71..8.74 rows=1 width=74) (actual time=0.010..0.010 rows=0 loops=1)
                                                                     Index Cond: ((time_id = 448540) AND (clienturi_parent_id = 649608573) AND (geo_id = 753) AND (useragent_id = 4176) AND (backend_id = 210) AND (proto_id = 67) AND (referrer_id = 11713775) AND (status_id = 1) AND (custom_id = 1))
                                                               ->  Index Scan Backward using usage_2017_07_time_id_clienturi_parent_id_geo_id_useragent__idx on usage_2017_07  (cost=0.71..8.75 rows=1 width=74) (actual time=0.012..0.012 rows=0 loops=1)
                                                                     Index Cond: ((time_id = 448540) AND (clienturi_parent_id = 649608573) AND (geo_id = 753) AND (useragent_id = 4176) AND (backend_id = 210) AND (proto_id = 67) AND (referrer_id = 11713775) AND (status_id = 1) AND (custom_id = 1))
                                                               ->  Index Scan Backward using usage_2017_08_time_id_clienturi_parent_id_geo_id_useragent__idx on usage_2017_08  (cost=0.71..8.75 rows=1 width=74) (actual time=0.012..0.012 rows=0 loops=1)
                                                                     Index Cond: ((time_id = 448540) AND (clienturi_parent_id = 649608573) AND (geo_id = 753) AND (useragent_id = 4176) AND (backend_id = 210) AND (proto_id = 67) AND (referrer_id = 11713775) AND (status_id = 1) AND (custom_id = 1))
                                                               ->  Index Scan Backward using usage_2017_09_time_id_clienturi_parent_id_geo_id_useragent__idx on usage_2017_09  (cost=0.71..8.74 rows=1 width
=74) (actual time=0.012..0.012 rows=0 loops=1)
                                                                     Index Cond: ((time_id = 448540) AND (clienturi_parent_id = 649608573) AND (geo_id = 753) AND (useragent_id = 4176) AND (backend_id = 21
0) AND (proto_id = 67) AND (referrer_id = 11713775) AND (status_id = 1) AND (custom_id = 1))
                                                               ->  Index Scan Backward using usage_2017_10_time_id_clienturi_parent_id_geo_id_useragent__idx on usage_2017_10  (cost=0.15..8.19 rows=1 width=74) (actual time=0.002..0.002 rows=0 loops=1)
                                                                     Index Cond: ((time_id = 448540) AND (clienturi_parent_id = 649608573) AND (geo_id = 753) AND (useragent_id = 4176) AND (backend_id = 210) AND (proto_id = 67) AND (referrer_id = 11713775) AND (status_id = 1) AND (custom_id = 1))
                                                         ->  Limit  (cost=0.00..5.58 rows=1 width=20) (actual time=0.006..0.006 rows=1 loops=10)
                                                               ->  Result  (cost=0.00..16.75 rows=3 width=20) (actual time=0.006..0.006 rows=1 loops=10)
                                                                     ->  Append  (cost=0.00..16.75 rows=3 width=20) (actual time=0.005..0.005 rows=1 loops=10)
                                                                           ->  Seq Scan on "time"  (cost=0.00..0.00 rows=1 width=20) (actual time=0.000..0.000 rows=0 loops=10)
                                                                                 Filter: (id = usage.time_id)
                                                                           ->  Index Scan using time_2016_pkey on time_2016  (cost=0.42..8.44 rows=1 width=20) (actual time=0.002..0.002 rows=0 loops=10)
                                                                                 Index Cond: (id = usage.time_id)
                                                                           ->  Index Scan using time_2017_pkey on time_2017  (cost=0.29..8.31 rows=1 width=20) (actual time=0.002..0.002 rows=1 loops=10)
                                                                                 Index Cond: (id = usage.time_id)
                                                   ->  Limit  (cost=0.00..5.53 rows=1 width=26) (actual time=0.005..0.005 rows=1 loops=10)
                                                         ->  Result  (cost=0.00..16.59 rows=3 width=26) (actual time=0.005..0.005 rows=1 loops=10)
                                                               ->  Append  (cost=0.00..16.59 rows=3 width=26) (actual time=0.004..0.004 rows=1 loops=10)
                                                                     ->  Seq Scan on geo  (cost=0.00..0.00 rows=1 width=64) (actual time=0.000..0.000 rows=0 loops=10)
                                                                           Filter: (id = usage.geo_id)
                                                                     ->  Index Scan using geo_2016_pkey on geo_2016  (cost=0.28..8.29 rows=1 width=7) (actual time=0.001..0.001 rows=0 loops=10)
                                                                           Index Cond: (id = usage.geo_id)
                                                                     ->  Index Scan using geo_2017_pkey on geo_2017  (cost=0.28..8.29 rows=1 width=7) (actual time=0.002..0.002 rows=1 loops=10)
                                                                           Index Cond: (id = usage.geo_id)
                                             ->  Limit  (cost=0.00..5.53 rows=1 width=38) (actual time=0.005..0.005 rows=1 loops=10)
                                                   ->  Result  (cost=0.00..16.59 rows=3 width=38) (actual time=0.004..0.004 rows=1 loops=10)
                                                         ->  Append  (cost=0.00..16.59 rows=3 width=38) (actual time=0.004..0.004 rows=1 loops=10)
                                                               ->  Seq Scan on useragent  (cost=0.00..0.00 rows=1 width=64) (actual time=0.000..0.000 rows=0 loops=10)
                                                                     Filter: (id = usage.useragent_id)
                                                               ->  Index Scan using useragent_2016_pkey on useragent_2016  (cost=0.28..8.30 rows=1 width=31) (actual time=0.001..0.001 rows=0 loops=10)
                                                                     Index Cond: (id = usage.useragent_id)
                                                               ->  Index Scan using useragent_2017_pkey on useragent_2017  (cost=0.28..8.29 rows=1 width=20) (actual time=0.002..0.002 rows=1 loops=10)
                                                                     Index Cond: (id = usage.useragent_id)
                                       ->  Limit  (cost=0.00..2.12 rows=1 width=4) (actual time=0.021..0.021 rows=1 loops=10)
                                             ->  Result  (cost=0.00..6.38 rows=3 width=4) (actual time=0.021..0.021 rows=1 loops=10)
                                                   ->  Append  (cost=0.00..6.38 rows=3 width=4) (actual time=0.021..0.021 rows=1 loops=10)
                                                         ->  Seq Scan on backend  (cost=0.00..0.00 rows=1 width=4) (actual time=0.000..0.000 rows=0 loops=10)
                                                               Filter: (id = usage.backend_id)
                                                         ->  Seq Scan on backend_2016  (cost=0.00..3.43 rows=1 width=4) (actual time=0.016..0.016 rows=0 loops=10)
                                                               Filter: (id = usage.backend_id)
                                                               Rows Removed by Filter: 194
                                                         ->  Seq Scan on backend_2017  (cost=0.00..2.95 rows=1 width=4) (actual time=0.003..0.003 rows=1 loops=10)
                                                               Filter: (id = usage.backend_id)
                                 ->  Limit  (cost=0.00..0.88 rows=1 width=14) (actual time=0.008..0.008 rows=1 loops=10)
                                       ->  Result  (cost=0.00..2.65 rows=3 width=14) (actual time=0.007..0.007 rows=1 loops=10)
                                             ->  Append  (cost=0.00..2.65 rows=3 width=14) (actual time=0.007..0.007 rows=1 loops=10)
                                                   ->  Seq Scan on proto  (cost=0.00..0.00 rows=1 width=32) (actual time=0.000..0.000 rows=0 loops=10)
                                                         Filter: (id = usage.proto_id)
                                                   ->  Seq Scan on proto_2016  (cost=0.00..1.61 rows=1 width=4) (actual time=0.005..0.005 rows=0 loops=10)
                                                         Filter: (id = usage.proto_id)
                                                         Rows Removed by Filter: 49
                                                   ->  Seq Scan on proto_2017  (cost=0.00..1.04 rows=1 width=5) (actual time=0.001..0.001 rows=1 loops=10)
                                                         Filter: (id = usage.proto_id)
                           ->  Limit  (cost=0.00..5.64 rows=1 width=25) (actual time=0.006..0.006 rows=1 loops=10)
                                 ->  Result  (cost=0.00..16.91 rows=3 width=25) (actual time=0.006..0.006 rows=1 loops=10)
                                       ->  Append  (cost=0.00..16.91 rows=3 width=25) (actual time=0.006..0.006 rows=1 loops=10)
                                             ->  Seq Scan on referrer  (cost=0.00..0.00 rows=1 width=32) (actual time=0.000..0.000 rows=0 loops=10)
                                                   Filter: (id = usage.referrer_id)
                                             ->  Index Scan using referrer_2016_pkey on referrer_2016  (cost=0.43..8.45 rows=1 width=22) (actual time=0.002..0.002 rows=0 loops=10)
                                                   Index Cond: (id = usage.referrer_id)
                                             ->  Index Scan using referrer_2017_pkey on referrer_2017  (cost=0.43..8.45 rows=1 width=22) (actual time=0.003..0.003 rows=1 loops=10)
                                                   Index Cond: (id = usage.referrer_id)
                     ->  Limit  (cost=0.00..5.54 rows=1 width=33) (actual time=0.003..0.003 rows=1 loops=10)
                           ->  Result  (cost=0.00..16.61 rows=3 width=33) (actual time=0.002..0.002 rows=1 loops=10)
                                 ->  Append  (cost=0.00..16.61 rows=3 width=33) (actual time=0.002..0.002 rows=1 loops=10)
                                       ->  Seq Scan on custom  (cost=0.00..0.00 rows=1 width=32) (actual time=0.000..0.000 rows=0 loops=10)
                                             Filter: (id = usage.custom_id)
                                       ->  Index Scan using custom_2016_pkey on custom_2016  (cost=0.15..8.17 rows=1 width=32) (actual time=0.001..0.001 rows=1 loops=10)
                                             Index Cond: (id = usage.custom_id)
                                       ->  Index Scan using custom_2017_pkey on custom_2017  (cost=0.42..8.44 rows=1 width=36) (never executed)
                                             Index Cond: (id = usage.custom_id)
               ->  Limit  (cost=0.00..3.27 rows=1 width=2) (actual time=0.003..0.003 rows=1 loops=10)
                     ->  Result  (cost=0.00..9.81 rows=3 width=2) (actual time=0.003..0.003 rows=1 loops=10)
                           ->  Append  (cost=0.00..9.81 rows=3 width=2) (actual time=0.002..0.002 rows=1 loops=10)
                                 ->  Seq Scan on status  (cost=0.00..0.00 rows=1 width=2) (actual time=0.000..0.000 rows=0 loops=10)
                                       Filter: (id = usage.status_id)
                                 ->  Index Scan using status_2016_pkey on status_2016  (cost=0.15..8.17 rows=1 width=2) (actual time=0.001..0.001 rows=1 loops=10)
                                       Index Cond: (id = usage.status_id)
                                 ->  Seq Scan on status_2017  (cost=0.00..1.64 rows=1 width=2) (never executed)
                                       Filter: (id = usage.status_id)
         ->  Limit  (cost=0.00..5.73 rows=1 width=73) (actual time=0.010..0.010 rows=1 loops=10)
               ->  Result  (cost=0.00..17.18 rows=3 width=73) (actual time=0.010..0.010 rows=1 loops=10)
                     ->  Append  (cost=0.00..17.18 rows=3 width=73) (actual time=0.010..0.010 rows=1 loops=10)
                           ->  Seq Scan on clienturi  (cost=0.00..0.00 rows=1 width=68) (actual time=0.000..0.000 rows=0 loops=10)
                                 Filter: (id = usage.clienturi_id)
                           ->  Index Scan using clienturi_2016_pkey1 on clienturi_2016  (cost=0.57..8.59 rows=1 width=73) (actual time=0.002..0.002 rows=0 loops=10)
                                 Index Cond: (id = usage.clienturi_id)
                           ->  Index Scan using clienturi_2017_pkey on clienturi_2017  (cost=0.57..8.59 rows=1 width=79) (actual time=0.006..0.006 rows=1 loops=10)
                                 Index Cond: (id = usage.clienturi_id)
 Planning time: 4.237 ms
 Execution time: 1.592 ms
(123 строки)
...
Рейтинг: 0 / 0
оптимизация limit по union all (когда лимит нельзя перенести в подзапрос)
    #39520571
Ролг Хупин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim BogukLegushkaпропущено...

еще не делал пагинацию ни разу, как правильно реализовать если не через limit/offset, который присутствует в текущей версии?

Ну вот например есть у вас таблица с постами в форуме. Следующая страница (ссылки) формируется не через limit/offset (которые не будут корректно работать если новые посты например появляются), а через where post_id<(последний post_id на текущей странице) LIMIT сколько вам надо.
Т.е. не ссылка на prev page вида skip=50 а ссылка на prev page вида before_post_id=[последний post_id на текущей странице].
Тогда как минимум это во многих случаях будет нормально работать по скорости и главное навигация не будет ломаться при появлении новых постов (что в 100% случаев происходит с limit/offset пагинацией).


PS: если у вас там 5-10 страниц максимум - можно и limit/offset а вот если потенциально 1000 страниц - то нет.

--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru

это в случае, если ид поста монотонная последовательность
...
Рейтинг: 0 / 0
оптимизация limit по union all (когда лимит нельзя перенести в подзапрос)
    #39520574
Ролг Хупин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim BogukLegushkaqwwq,
а есть какие нибудь методы как решить? в голову ничего не приходит
не хочется ковырять все записи что бы потом отобрать только 10

писать запросы руками и вставлять limit 10 в обе части union all
насколько поможет - не факт но это единственное куда вообще можно копать.
Что там позволяет или нет ваш движек - ваши проблемы, можно всегда запрос в хранимку засунуть если очень хочется.


--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru

вообще-то думается, что в таком случае результат объединения в общем случаем будет неправильный
...
Рейтинг: 0 / 0
оптимизация limit по union all (когда лимит нельзя перенести в подзапрос)
    #39520622
Melkij
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ролг Хупинэто в случае, если ид поста монотонная последовательность
Это в любом случае для стабильно сортируемого множества. А для offset пагинации стабильная сортировка необходима тем более, поэтому применимо.
http://use-the-index-luke.com/sql/partial-results/fetch-next-page
...
Рейтинг: 0 / 0
оптимизация limit по union all (когда лимит нельзя перенести в подзапрос)
    #39520682
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ролг ХупинMaxim Bogukпропущено...


писать запросы руками и вставлять limit 10 в обе части union all
насколько поможет - не факт но это единственное куда вообще можно копать.
Что там позволяет или нет ваш движек - ваши проблемы, можно всегда запрос в хранимку засунуть если очень хочется.


--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru

вообще-то думается, что в таком случае результат объединения в общем случаем будет неправильный

Обоснуйте? ;)
Или приведите контрпример.

--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru
...
Рейтинг: 0 / 0
оптимизация limit по union all (когда лимит нельзя перенести в подзапрос)
    #39520721
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LeXa NalBatПостгрес может эффективно выполнить такой запрос - выбрав не все строки, а только нужные по лимиту. Важно, чтобы на каждой таблице существовал нужный индекс, чтобы не требовалось переупорядочивание строк. Тогда сможет использовать Merge Append, джоин по Nested Loop и Limit.

дык я об том и писал. 20791161


Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
SELECT part, t_id, fld
  FROM public.t_t
  order by 2
limit 10;
======================
'Limit  (cost=0.69..1.55 rows=10 width=11) (actual time=0.052..0.060 rows=10 loops=1)'
'  Output: t_t.part, t_t.t_id, t_t.fld'
'  Buffers: shared hit=7'
'  ->  Merge Append  (cost=0.69..86.08 rows=1001 width=11) (actual time=0.052..0.059 rows=10 loops=1)'
'        Sort Key: t_t.t_id'
'        Buffers: shared hit=7'
'        ->  Index Scan using t_t_pkey on public.t_t  (cost=0.12..8.14 rows=1 width=40) (actual time=0.003..0.003 rows=0 loops=1)'
'              Output: t_t.part, t_t.t_id, t_t.fld'
'              Buffers: shared hit=1'
'        ->  Index Scan using t_1_pkey on public.t_1  (cost=0.27..29.77 rows=500 width=11) (actual time=0.009..0.011 rows=5 loops=1)'
'              Output: t_1.part, t_1.t_id, t_1.fld'
'              Buffers: shared hit=3'
'        ->  Index Scan using t_2_pkey on public.t_2  (cost=0.27..29.77 rows=500 width=11) (actual time=0.008..0.008 rows=6 loops=1)'
'              Output: t_2.part, t_2.t_id, t_2.fld'
'              Buffers: shared hit=3'
'Planning time: 0.190 ms'
'Execution time: 0.093 ms'



или для честного юниона
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
SELECT part, t_id, fld
FROM public.t_1
UNION ALL
SELECT part, t_id, fld
FROM public.t_1
order by 2
limit 10;
----------------------------------
'Limit  (cost=0.56..1.27 rows=10 width=11) (actual time=0.040..0.048 rows=10 loops=1)'
'  Output: t_1.part, t_1.t_id, t_1.fld'
'  Buffers: shared hit=6'
'  ->  Merge Append  (cost=0.56..72.06 rows=1000 width=11) (actual time=0.039..0.046 rows=10 loops=1)'
'        Sort Key: t_1.t_id'
'        Buffers: shared hit=6'
'        ->  Index Scan using t_1_pkey on public.t_1  (cost=0.27..29.77 rows=500 width=11) (actual time=0.030..0.032 rows=6 loops=1)'
'              Output: t_1.part, t_1.t_id, t_1.fld'
'              Buffers: shared hit=3'
'        ->  Index Scan using t_1_pkey on public.t_1 t_1_1  (cost=0.27..29.77 rows=500 width=11) (actual time=0.007..0.009 rows=5 loops=1)'
'              Output: t_1_1.part, t_1_1.t_id, t_1_1.fld'
'              Buffers: shared hit=3'
'Planning time: 0.176 ms'
'Execution time: 0.080 ms'



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

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
SELECT part, t_id, fld
FROM public.t_1
order by 2,1
limit 10;
------------------------
'Limit  (cost=18.80..18.83 rows=10 width=11) (actual time=0.180..0.183 rows=10 loops=1)'
'  Output: part, t_id, fld'
'  Buffers: shared hit=3'
'  ->  Sort  (cost=18.80..20.05 rows=500 width=11) (actual time=0.178..0.180 rows=10 loops=1)'
'        Output: part, t_id, fld'
'        Sort Key: t_1.t_id, t_1.part'
'        Sort Method: top-N heapsort  Memory: 25kB'
'        Buffers: shared hit=3'
'        ->  Seq Scan on public.t_1  (cost=0.00..8.00 rows=500 width=11) (actual time=0.016..0.088 rows=500 loops=1)'
'              Output: part, t_id, fld'
'              Buffers: shared hit=3'
'Planning time: 0.114 ms'
'Execution time: 0.211 ms'



я где-то давно тут показывал, как это обрезать ("без аппенда") скл-м.

(в процессе мердж оппенда с индексным префиксом и уникализирующем постфиксе в сортировке это делать, алгоритмически, не сложнее, если у тебя в руках seek, да даже на скл это пишется, в рекурсивеном т.с. стиле. хотя и немного лишнего. проще грубо взять по ломтю, и отресортив все выбросить.
...
Рейтинг: 0 / 0
оптимизация limit по union all (когда лимит нельзя перенести в подзапрос)
    #39520765
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
qwwq,

тут кажется не показывал. соврал

вот для аппенда то же сделал.
т.ч. зафиксирую, чтобы былО куда послать.
стыд и срам :
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
SELECT * FROM t_t 
ORDER BY fld,t_id limit 30
-------------------------------------
Limit  (cost=9034.53..9034.61 rows=30 width=12) (actual time=95.907..95.916 rows=30 loops=1)
  Output: t_t.part, t_t.t_id, t_t.fld
  Buffers: shared hit=1088
  ->  Sort  (cost=9034.53..9537.04 rows=201003 width=12) (actual time=95.905..95.911 rows=30 loops=1)
        Output: t_t.part, t_t.t_id, t_t.fld
        Sort Key: t_t.fld, t_t.t_id
        Sort Method: top-N heapsort  Memory: 26kB
        Buffers: shared hit=1088
        ->  Append  (cost=0.00..3098.02 rows=201003 width=12) (actual time=0.010..48.808 rows=201002 loops=1)
              Buffers: shared hit=1088
              ->  Seq Scan on public.t_t  (cost=0.00..0.00 rows=1 width=40) (actual time=0.003..0.003 rows=0 loops=1)
                    Output: t_t.part, t_t.t_id, t_t.fld
              ->  Seq Scan on public.t_1  (cost=0.00..1549.02 rows=100502 width=12) (actual time=0.006..12.942 rows=100502 loops=1)
                    Output: t_1.part, t_1.t_id, t_1.fld
                    Buffers: shared hit=544
              ->  Seq Scan on public.t_2  (cost=0.00..1549.00 rows=100500 width=12) (actual time=0.007..10.542 rows=100500 loops=1)
                    Output: t_2.part, t_2.t_id, t_2.fld
                    Buffers: shared hit=544
Planning time: 0.205 ms
Execution time: 95.946 ms



и через мердж-аппенд с ресортом:
Код: 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.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
SELECT * FROM (
SELECT * FROM t_t 

ORDER BY fld
LIMIT 30 +(SELECT count(1) FROM public.t_t  
	WHERE fld = (SELECT fld from (SELECT fld FROM public.t_t ORDER BY 1 LIMIT 30) last ORDER BY fld desc LIMIT 1)
			) --число последних значений неуникального. все сложнее (только в SQL) когда nullable, 
) buff
ORDER BY fld,t_id limit 30
----------------------------------------------------------------------------
Limit  (cost=2145.10..2145.18 rows=30 width=12) (actual time=0.918..0.932 rows=30 loops=1)
  Output: t_t.part, t_t.t_id, t_t.fld
  Buffers: shared hit=150
  ->  Sort  (cost=2145.10..2195.35 rows=20100 width=12) (actual time=0.917..0.923 rows=30 loops=1)
        Output: t_t.part, t_t.t_id, t_t.fld
        Sort Key: t_t.fld, t_t.t_id
        Sort Method: top-N heapsort  Memory: 26kB
        Buffers: shared hit=150
        ->  Limit  (cost=12.04..1350.46 rows=20100 width=12) (actual time=0.308..0.733 rows=132 loops=1)
              Output: t_t.part, t_t.t_id, t_t.fld
              Buffers: shared hit=150
              InitPlan 2 (returns $1)
                ->  Aggregate  (cost=11.30..11.31 rows=1 width=8) (actual time=0.273..0.273 rows=1 loops=1)
                      Output: count(1)
                      Buffers: shared hit=12
                      InitPlan 1 (returns $0)
                        ->  Limit  (cost=2.55..2.55 rows=1 width=4) (actual time=0.117..0.117 rows=1 loops=1)
                              Output: t_t_1.fld
                              Buffers: shared hit=7
                              ->  Sort  (cost=2.55..2.63 rows=30 width=4) (actual time=0.117..0.117 rows=1 loops=1)
                                    Output: t_t_1.fld
                                    Sort Key: t_t_1.fld DESC
                                    Sort Method: top-N heapsort  Memory: 25kB
                                    Buffers: shared hit=7
                                    ->  Limit  (cost=0.73..2.10 rows=30 width=4) (actual time=0.051..0.081 rows=30 loops=1)
                                          Output: t_t_1.fld
                                          Buffers: shared hit=7
                                          ->  Merge Append  (cost=0.73..9160.11 rows=201003 width=4) (actual time=0.051..0.073 rows=30 loops=1)
                                                Sort Key: t_t_1.fld
                                                Buffers: shared hit=7
                                                ->  Index Only Scan using t_t_fld_idx on public.t_t t_t_1  (cost=0.12..8.14 rows=1 width=32) (actual time=0.005..0.005 rows=0 loops=1)
                                                      Output: t_t_1.fld
                                                      Heap Fetches: 0
                                                      Buffers: shared hit=1
                                                ->  Index Only Scan using t_1_fld_idx on public.t_1 t_1_1  (cost=0.29..2747.82 rows=100502 width=4) (actual time=0.023..0.034 rows=30 loops=1)
                                                      Output: t_1_1.fld
                                                      Heap Fetches: 0
                                                      Buffers: shared hit=3
                                                ->  Index Only Scan using t_2_fld_idx on public.t_2 t_2_1  (cost=0.29..2715.79 rows=100500 width=4) (actual time=0.019..0.019 rows=1 loops=1)
                                                      Output: t_2_1.fld
                                                      Heap Fetches: 0
                                                      Buffers: shared hit=3
                      ->  Append  (cost=0.00..8.73 rows=9 width=0) (actual time=0.161..0.239 rows=102 loops=1)
                            Buffers: shared hit=12
                            ->  Seq Scan on public.t_t t_t_2  (cost=0.00..0.00 rows=1 width=0) (actual time=0.004..0.004 rows=0 loops=1)
                                  Filter: (t_t_2.fld = $0)
                            ->  Index Only Scan using t_1_fld_idx on public.t_1 t_1_2  (cost=0.29..4.36 rows=4 width=0) (actual time=0.156..0.188 rows=102 loops=1)
                                  Index Cond: (t_1_2.fld = $0)
                                  Heap Fetches: 0
                                  Buffers: shared hit=10
                            ->  Index Only Scan using t_2_fld_idx on public.t_2 t_2_2  (cost=0.29..4.36 rows=4 width=0) (actual time=0.021..0.021 rows=0 loops=1)
                                  Index Cond: (t_2_2.fld = $0)
                                  Heap Fetches: 0
                                  Buffers: shared hit=2
              ->  Merge Append  (cost=0.73..13385.08 rows=201003 width=12) (actual time=0.029..0.414 rows=132 loops=1)
                    Sort Key: t_t.fld
                    Buffers: shared hit=138
                    ->  Index Scan using t_t_fld_idx on public.t_t  (cost=0.12..8.14 rows=1 width=40) (actual time=0.002..0.002 rows=0 loops=1)
                          Output: t_t.part, t_t.t_id, t_t.fld
                          Buffers: shared hit=1
                    ->  Index Scan using t_1_fld_idx on public.t_1  (cost=0.29..4863.84 rows=100502 width=12) (actual time=0.013..0.221 rows=103 loops=1)
                          Output: t_1.part, t_1.t_id, t_1.fld
                          Buffers: shared hit=105
                    ->  Index Scan using t_2_fld_idx on public.t_2  (cost=0.29..4824.75 rows=100500 width=12) (actual time=0.011..0.103 rows=30 loops=1)
                          Output: t_2.part, t_2.t_id, t_2.fld
                          Buffers: shared hit=32
Planning time: 0.550 ms
Execution time: 1.149 ms



:
...
Рейтинг: 0 / 0
оптимизация limit по union all (когда лимит нельзя перенести в подзапрос)
    #39520904
Фотография Legushka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
qwwq, это какая то магия, подставил свои таблицы в ваш пример
вот два плана
стандартная сортировка
https://explain.depesz.com/s/Rz2

и магия)
https://explain.depesz.com/s/oEhM

я в шоке)))
могли бы вы подробно рассказать что происходит на человеческом языке:
что это значит:
число последних значений неуникального. все сложнее (только в SQL) когда nullable

и есть ли подводные камни?
...
Рейтинг: 0 / 0
оптимизация limit по union all (когда лимит нельзя перенести в подзапрос)
    #39520988
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Legushka,

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

если у вас не этот случай (сортировка по листу, лидирующая часть которого совпадает с неуникальным индексом, и есть какой--то постфикс) -- то у вас не магия, а сапоги в смятку.
...
Рейтинг: 0 / 0
оптимизация limit по union all (когда лимит нельзя перенести в подзапрос)
    #39521047
Ролг Хупин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim BogukРолг Хупинпропущено...


вообще-то думается, что в таком случае результат объединения в общем случаем будет неправильный

Обоснуйте? ;)
Или приведите контрпример.

--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru

не буду

"не всегда" будет правильным.
нет гарантии, что будет правильным
...
Рейтинг: 0 / 0
оптимизация limit по union all (когда лимит нельзя перенести в подзапрос)
    #39521061
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ролг ХупинMaxim Bogukпропущено...


Обоснуйте? ;)
Или приведите контрпример.

--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru

не буду

"не всегда" будет правильным.
нет гарантии, что будет правильным

Приведите пример где оно МОЖЕТ теоретически дать неверный ответ. ;)
Благо это самое стандартное преобразование для union all из тех что я знаю для ускорения.


--
Maxim Boguk
лучшая поддержка PostgreSQL: dataegret.ru
...
Рейтинг: 0 / 0
оптимизация limit по union all (когда лимит нельзя перенести в подзапрос)
    #39521087
Фотография vyegorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
qwwq,

А можете предоставить скрипты для вашей таблицы `t_t`? чтобы был самодостаточный демонстрационный пример?
...
Рейтинг: 0 / 0
25 сообщений из 35, страница 1 из 2
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / оптимизация limit по union all (когда лимит нельзя перенести в подзапрос)
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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