|
Долгий count(*)
|
|||
---|---|---|---|
#18+
Доброго дня, коллеги. PostgreSQL 10.3 Вопрос достаточно детский, но ничего путного не нашёл. Суть: долго выполняется запрос count(*): Код: sql 1. 2. 3. 4. 5. 6.
Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
Поисковые столбцы индексированы, всё время тратиться на "Aggregate" Смотрел в сторону Loose indexscan, но по-моему это не то... ... |
|||
:
Нравится:
Не нравится:
|
|||
19.04.2018, 00:56 |
|
Долгий count(*)
|
|||
---|---|---|---|
#18+
sKot, первый вопрос: почему вы джойните две таблицы? если там у вас инер джойн да и селект по где ид ровен Х. ... |
|||
:
Нравится:
Не нравится:
|
|||
19.04.2018, 07:00 |
|
Долгий count(*)
|
|||
---|---|---|---|
#18+
sKotДоброго дня, коллеги. PostgreSQL 10.3 Вопрос достаточно детский, но ничего путного не нашёл. Суть: долго выполняется запрос count(*): Код: sql 1. 2. 3. 4. 5. 6.
Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
Поисковые столбцы индексированы, всё время тратиться на "Aggregate" Смотрел в сторону Loose indexscan, но по-моему это не то... вы неправильно читаете план. (я впрочем тоже его неверно читаю) время тратится на чтение 28 лямов 5.5сек и свертку нестед лупом еще с 1-й -- с 0-й по 9.-ю сек. но ещё 3 сек на до-подбор агрегатом --дороговато в выдаче у вас число "28626778" ? никакой луз не поможет. можете отвакуумиться , или переиндексироваться --7468 раз оно лазало в кучу из иоса. но это поможет временно и не сильно. а покажите хохмы ради план примерно такой Код: sql 1. 2. 3. 4. 5. 6. 7.
[src sql] ... |
|||
:
Нравится:
Не нравится:
|
|||
19.04.2018, 07:54 |
|
Долгий count(*)
|
|||
---|---|---|---|
#18+
Lonepsycho, спасибо, с этим косяком я буду разбираться, для count(*) join не нужен. Запрос создаётся динамически движком отображения журналов. Точнее создаётся два одинаковых (по джойнам и фильтрам) запроса - один тащит данные (и в нём как раз без джойна не обойтисть), а второй считает общее кол-во строк, попавших в результирующее множество. Попробовал без джойна.... Даже не знаю что сказать: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15.
... |
|||
:
Нравится:
Не нравится:
|
|||
19.04.2018, 12:50 |
|
Долгий count(*)
|
|||
---|---|---|---|
#18+
qwwq, Спасибо :) Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15.
Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18.
... |
|||
:
Нравится:
Не нравится:
|
|||
19.04.2018, 12:55 |
|
Долгий count(*)
|
|||
---|---|---|---|
#18+
qwwq, да, в выдаче 28626778. Это журнал лога, в нём ~40 млн записей, из них 28626778 - протокол SOAP. Данный запрос взят для примера, если взять другой протокол, то картина примерно такая же. l__r.LOG_PROTO_ID = 3 показал самый долгий результат (т.к. этих записей больше всего), поэтому я и привёл этот запрос в качестве примера. ... |
|||
:
Нравится:
Не нравится:
|
|||
19.04.2018, 12:59 |
|
Долгий count(*)
|
|||
---|---|---|---|
#18+
sKot, "паралел" вам отстрелить надо. или костами загнобить. ... |
|||
:
Нравится:
Не нравится:
|
|||
19.04.2018, 13:02 |
|
Долгий count(*)
|
|||
---|---|---|---|
#18+
если возвращается столько строк, то нафига индекс по LOG_PROTO_ID вообще нужен.. исподльзуйте партицирование по этому полю ... |
|||
:
Нравится:
Не нравится:
|
|||
19.04.2018, 13:14 |
|
Долгий count(*)
|
|||
---|---|---|---|
#18+
+не знаю, насколько вам актуально из-за того, что запрос генерируете не вы, но 1. если скорость чтения кол-ва логов важнее скорости вставки логов, то вешайте триггер, который апдейтит таблицу с количеством на каждый LOG_PROTO_ID 2. если информация не нужна актуальная прям на данный момент времени, создайте матвью с группировкой и количеством на каждый LOG_PROTO_ID и апдейтите её раз в час, например 3. если точное кол-во не важно (2237853423 или 2237853689), то вместо count используйте данные статистики из плана по запросу where LOG_PROTO_ID = ? ... |
|||
:
Нравится:
Не нравится:
|
|||
19.04.2018, 13:23 |
|
Долгий count(*)
|
|||
---|---|---|---|
#18+
bdsm_sql, партиционирование не очень поможет, т.к. работа с таблицей ведётся через механизм журналов, который на партиционирование (а в случае с PostgreSQL - работы с несколькими таблицами вместо одной) не заточен :( ... |
|||
:
Нравится:
Не нравится:
|
|||
19.04.2018, 14:45 |
|
Долгий count(*)
|
|||
---|---|---|---|
#18+
bdsm_sql, автор3. если точное кол-во не важно (2237853423 или 2237853689), то вместо count используйте данные статистики из плана по запросу where LOG_PROTO_ID = ? Идея хороша, буду её думать :) Спасибо! ... |
|||
:
Нравится:
Не нравится:
|
|||
19.04.2018, 14:47 |
|
Долгий count(*)
|
|||
---|---|---|---|
#18+
qwwq, автор"паралел" вам отстрелить надо. или костами загнобить. Я дико прошу прощения, но не понял ни первый, ни второй совет: 1. Я так понимаю, надо каким-то образом включить многопоточное выполнение запроса "count(*)..."? Если да, то имеется в виду установку параметра "max_parallel_workers_per_gather" в файле pgsql.conf? 2. Как загнобить костами? Тут я даже гуглить затрудняюсь :) ... |
|||
:
Нравится:
Не нравится:
|
|||
19.04.2018, 14:57 |
|
Долгий count(*)
|
|||
---|---|---|---|
#18+
sKotqwwq, автор"паралел" вам отстрелить надо. или костами загнобить. Я дико прошу прощения, но не понял ни первый, ни второй совет: 1. Я так понимаю, надо каким-то образом включить многопоточное выполнение запроса "count(*)..."? Если да, то имеется в виду установку параметра "max_parallel_workers_per_gather" в файле pgsql.conf? 2. Как загнобить костами? Тут я даже гуглить затрудняюсь :) всё вы поняли, прямо в сессии где замеряете ставите Код: sql 1.
а зачем гуглить. берете rtfm => https://postgrespro.ru/docs/enterprise/10/when-can-parallel-query-be-used и в 0 приближении имеете список парамсов, которые можно засетить в сессии или конфе. или вот тут посмотрите https://habrahabr.ru/post/305662/ парамсы пока не устоялись, но примерный вектор. ... |
|||
:
Нравится:
Не нравится:
|
|||
19.04.2018, 15:13 |
|
Долгий count(*)
|
|||
---|---|---|---|
#18+
sKotbdsm_sql, партиционирование не очень поможет, т.к. работа с таблицей ведётся через механизм журналов, который на партиционирование (а в случае с PostgreSQL - работы с несколькими таблицами вместо одной) не заточен :( механизм журналов - это что? некая хрень, которая шлёт запросы? если да, то в 10ке партицирование из коробки, тупое, но под эту задачу подойдёт. работу будет как с одной таблицей, т.е. для приложения без изменений. если же механизм журналов это какая-то репликация, то там могут быть тонкости ... |
|||
:
Нравится:
Не нравится:
|
|||
19.04.2018, 15:20 |
|
Долгий count(*)
|
|||
---|---|---|---|
#18+
sKotbdsm_sql, автор3. если точное кол-во не важно (2237853423 или 2237853689), то вместо count используйте данные статистики из плана по запросу where LOG_PROTO_ID = ? Идея хороша, буду её думать :) Спасибо! https://wiki.postgresql.org/wiki/Count_estimate ... |
|||
:
Нравится:
Не нравится:
|
|||
19.04.2018, 15:21 |
|
Долгий count(*)
|
|||
---|---|---|---|
#18+
qwwq, c параллелизмом я, собственно, этот мануал по ПостгресПро и нагуглил, а вот с костами, которыми надо гнобить я не знаю куда лезть :) Уж слишком формулировка бандитская... ... |
|||
:
Нравится:
Не нравится:
|
|||
19.04.2018, 17:13 |
|
Долгий count(*)
|
|||
---|---|---|---|
#18+
bdsm_sql, спасибо, посмотрю партиционирование в 10. Пока я видел только костыли на триггерах и нескольких таблицах. ... |
|||
:
Нравится:
Не нравится:
|
|||
19.04.2018, 17:15 |
|
Долгий count(*)
|
|||
---|---|---|---|
#18+
sKotqwwq, c параллелизмом я, собственно, этот мануал по ПостгресПро и нагуглил, а вот с костами, которыми надо гнобить я не знаю куда лезть :) Уж слишком формулировка бандитская... а голова вам на что ? вы в её кюшаешь ? в многострадальную. бывает. по ссылке авторя общего числа этих процессов значением max_worker_processes. (я немного сдвинул фокус) попали на набор парамсов для и на страничке планировщика ищем константы для рулежки https://postgrespro.ru/docs/enterprise/10/runtime-config-query авторparallel_setup_cost (floating point) Задаёт приблизительную стоимость запуска параллельных рабочих процессов. Значение по умолчанию — 1000. parallel_tuple_cost (floating point) Задаёт приблизительную стоимость передачи одного кортежа от параллельного рабочего процесса другому процессу. Значение по умолчанию — 0.1. min_parallel_table_scan_size (integer) Задаёт минимальный объём данных таблицы, подлежащий сканированию, при котором может применяться параллельное сканирование. Для параллельного последовательного сканирования объём сканируемых данных всегда равняется размеру таблицы, но когда используются индексы, этот объём обычно меньше. Значение по умолчанию — 8 мегабайт (8MB). min_parallel_index_scan_size (integer) Задаёт минимальный объём данных индекса, подлежащий сканированию, при котором может применяться параллельное сканирование. Заметьте, что при параллельном сканировании по индексу обычно не затрагивается весь индекс; здесь учитывается число страниц, которое по мнению планировщика будет затронуто при сканировании. Значение по умолчанию — 512 килобайт (512kB). дальше жевать , или направление понятно ? но я только про то, что параллельно оно у вас медленнее чем в лоб. с чего бы это. подрихтовать бы. ... |
|||
:
Нравится:
Не нравится:
|
|||
19.04.2018, 17:59 |
|
Долгий count(*)
|
|||
---|---|---|---|
#18+
qwwq, спасибо за то что разжевали. Направление понятно, но вот про рихтовку, чтобы в два потока было быстрее чем в один: это тоже константами планировщика делается? ... |
|||
:
Нравится:
Не нравится:
|
|||
19.04.2018, 19:25 |
|
Долгий count(*)
|
|||
---|---|---|---|
#18+
sKotqwwq, спасибо за то что разжевали. Направление понятно, но вот про рихтовку, чтобы в два потока было быстрее чем в один: это тоже константами планировщика делается?думаю только железом. там накладных куча, при передаче данных от воркеров и синхронизации. (но коунт компактен -- там только поделить данные без накладок -- примерно обменяться например адресами страниц) оттюнить можно только позывы к переходу в параллельный режим. все остальное -- от алгоритмов и железа. ... |
|||
:
Нравится:
Не нравится:
|
|||
19.04.2018, 20:02 |
|
Долгий count(*)
|
|||
---|---|---|---|
#18+
qwwq, bdsm_sql, огромное вам спасибо! Вы мне реально помогли! Окончательное решение такое: Для больших таблиц (>40 млн) и связанных с ними таблиц, я сделал получение кол-ва записей через план запроса ( https://wiki.postgresql.org/wiki/Count_estimate), bdsm_sql, спасибо тебе! Если кол-во строк полученных из плана <20000, то выполняется обычный count(*). Нахардкодить в данном случае не получится, т.к. таблицы и джойны к ним, а также "where..." динамические. В результате журнал логов стал открываться не 12+ секунд, а 0.02-0.06 сек. Вопрос можно считать закрытым. P.S. Интересное наблюдение: про получение кол-ва записей из плана запроса я читал и ранее, больше года назад. Но пока кто-то не ткнёт мордой: "вот оно - решение", даже не задумаешься о применении этого способа. И это не единичный случай это система.... ... |
|||
:
Нравится:
Не нравится:
|
|||
20.04.2018, 03:23 |
|
|
start [/forum/topic.php?fid=53&msg=39633221&tid=1995819]: |
0ms |
get settings: |
10ms |
get forum list: |
13ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
30ms |
get topic data: |
11ms |
get forum data: |
3ms |
get page messages: |
53ms |
get tp. blocked users: |
1ms |
others: | 15ms |
total: | 144ms |
0 / 0 |