powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Слишком оптимистичный LIMIT
2 сообщений из 2, страница 1 из 1
Слишком оптимистичный LIMIT
    #38953669
Nitro_Junkie
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть такой простой запрос:

Код: sql
1.
2.
3.
4.
SELECT t0.key0
FROM ZReport_receiptDetail t0
WHERE t0.ZReport_receiptReceiptDetail_ReceiptDetail=9426585
ORDER BY t0.key0 DESC LIMIT 19



При выполнении получаем такой, очевидно неправильный план:

Код: sql
1.
2.
3.
4.
5.
6.
7.
"Limit  (cost=0.43..622.60 rows=19 width=4) (actual time=1197.437..1197.573 rows=19 loops=1)"
"  Output: key0"
"  ->  Index Scan Backward using zreport_receiptdetail_pkey on public.zreport_receiptdetail t0  (cost=0.43..209017.54 rows=6383 width=4) (actual time=1197.435..1197.571 rows=19 loops=1)"
"        Output: key0"
"        Filter: (t0.zreport_receiptreceiptdetail_receiptdetail = 9426585)"
"        Rows Removed by Filter: 3472089"
"Total runtime: 1197.586 ms"



Меняю запрос на:
Код: sql
1.
2.
3.
4.
SELECT t0.key0
FROM ZReport_receiptDetail t0
WHERE t0.ZReport_receiptReceiptDetail_ReceiptDetail=9426585
ORDER BY t0.key0+2 DESC LIMIT 19



Получаю :

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
"Limit  (cost=1087.41..1087.46 rows=19 width=4) (actual time=1.570..1.571 rows=19 loops=1)"
"  Output: key0, ((key0 + 2))"
"  ->  Sort  (cost=1087.41..1103.37 rows=6383 width=4) (actual time=1.569..1.569 rows=19 loops=1)"
"        Output: key0, ((key0 + 2))"
"        Sort Key: ((t0.key0 + 2))"
"        Sort Method: top-N heapsort  Memory: 25kB"
"        ->  Index Scan using ddd on public.zreport_receiptdetail t0  (cost=0.43..919.92 rows=6383 width=4) (actual time=0.034..1.250 rows=4739 loops=1)"
"              Output: key0, (key0 + 2)"
"              Index Cond: (t0.zreport_receiptreceiptdetail_receiptdetail = 9426585)"
"Total runtime: 1.586 ms"



Собсно логику Postgres можно понять. Он берет cost получения всех записей 209017.54 делит на количество результирующих рядов 6383 и умножает на кол-во LIMIT 19 - и получает 622,6. При этом у плана с поиском всех receiptDetail с заданным значением, а потом упорядочивания cost 1000, то есть формально выше.

Но при этом проблема в том, что Postgres естественным образом не учитывает корелляцию (так как чеки проводятся порциями и номера чеков идут по возрастанию), и тем самым "плюет на дисперсию".

Как вообще можно бороться с такими случаями? Может есть какой-то способ увеличить cost при Limit'е (чтобы лучше работать в крайних случаях)?
...
Рейтинг: 0 / 0
Слишком оптимистичный LIMIT
    #38953711
qwwq
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nitro_Junkie,

как бороться -- вы сами уже успешно заборолись.

а если запросы часты --
Код: sql
1.
CREATE INDEX  ON ZReport_receiptDetai (ZReport_receiptReceiptDetail_ReceiptDetail,key0)


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


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