|
seq_scan при подходящей для индекса селективности
|
|||
---|---|---|---|
#18+
Ребят, ткните пожалуйста, где можно что то дельное почитать. Проблема такая. postgresql 12.5 запрос Select t2.* FROM t1 JOIN t2 on t2.id=t1.t2_id WHERE t1.id = 5358; t2.id primary key в таблице t2 6млн записей. В итоге если по t1.id = 5358 отобрано 30400 записей, то используется индекс t2.id primary key, с другим t1.id = 5810 из t1 отбирается 30500 записей и уже идет seq_scan таблицы t2. В итоге 30400 записей достается 0.33ms, а всего на 100 больше 30500 достается уже больше 3секунд. 30500 от 6ти млн это же меньше 1% , селективность для использования индекса хорошая, почему тогда оптимизатор выбирает seq_sqan? В какую сторону копать? Подбирать настройки сервера? Заранее спасибо. ... |
|||
:
Нравится:
Не нравится:
|
|||
03.08.2020, 14:00 |
|
seq_scan при подходящей для индекса селективности
|
|||
---|---|---|---|
#18+
Дальнейшие эксперименты Select t2.* FROM t1 JOIN t2 on t2.id=t1.t2_id WHERE t1.id = 6150; отбирается 40000 записей, используется индекс. Select t2.* FROM t1 JOIN t2 on t2.id=t1.t2_id WHERE t1.id = 5810 ; отбирается 30500 записей, seq_scan Select t2.id FROM t1 JOIN t2 on t2.id=t1.t2_id WHERE t1.id = 5810 ; используется индекс Select t1.* FROM t1 JOIN t2 on t2.id=t1.t2_id WHERE t1.id = 5810 ; используется индекс Select t1.*, t2.id FROM t1 JOIN t2 on t2.id=t1.t2_id WHERE t1.id = 5810 ; используется индекс Select t1.*, t2.id, t2.group_id FROM t1 JOIN t2 on t2.id=t1.t2_id WHERE t1.id = 5810 ; seq_scan ... |
|||
:
Нравится:
Не нравится:
|
|||
03.08.2020, 14:39 |
|
seq_scan при подходящей для индекса селективности
|
|||
---|---|---|---|
#18+
Select t2.* FROM t2 JOIN t1 on t2.id=t1.t2_id WHERE t1.id = 5810; seq_scan таблицы t2 Select t2.* FROM t2 WHERE t2.id IN (SELECT t2_id FROM t1 where t1.id = 5810); index scan t2.id pk ... |
|||
:
Нравится:
Не нравится:
|
|||
03.08.2020, 15:00 |
|
seq_scan при подходящей для индекса селективности
|
|||
---|---|---|---|
#18+
explain (analyze) показывайте. Вслепую ощупывать слона конечно увлекательно, не малопродуктивно. И на всякий случай уточните какие у вас seq_page_cost, random_page_cost настроены. ... |
|||
:
Нравится:
Не нравится:
|
|||
03.08.2020, 15:02 |
|
seq_scan при подходящей для индекса селективности
|
|||
---|---|---|---|
#18+
kliff Select t2.* FROM t1 JOIN t2 on t2.id=t1.t2_id WHERE t1.id = 5358; Можете поменять условие в тексте запроса: Select t2.* FROM t1 JOIN t2 on t2.id=t1.t2_id WHERE t2 .id = 5358; ? Скорее всего дело в неправильной оценке n_distinct для столбца t1.id. Что показывает: select n_distinct from pg_stats where tablename = 't1' and attname = 'id'; ... |
|||
:
Нравится:
Не нравится:
|
|||
03.08.2020, 15:06 |
|
seq_scan при подходящей для индекса селективности
|
|||
---|---|---|---|
#18+
Melkij explain (analyze) показывайте. Вслепую ощупывать слона конечно увлекательно, не малопродуктивно. И на всякий случай уточните какие у вас seq_page_cost, random_page_cost настроены. На другом сервере нашел тоже схожую ситуацию, postgres 9.6 авторexplain(analyze, buffers)select m.* from messages m join messages_users u on u.mess_id = m.id where u.user_id = 140777; Nested Loop (cost=1.00..253328.46 rows=29696 width=44) (actual time=0.078..180.555 rows=31920 loops=1) Buffers: shared hit=143395 -> Index Scan using messages_users_user_id_idx on messages_users u (cost=0.56..72884.30 rows=29696 width=4) (actual time=0.061..80.524 rows=31920 loops=1) Index Cond: (user_id = 140777) Buffers: shared hit=15548 -> Index Scan using pk_rep_messages on rep_messages m (cost=0.43..6.07 rows=1 width=44) (actual time=0.003..0.003 rows=1 loops=31920) Index Cond: (id = u.mess_id) Buffers: shared hit=127847 Planning time: 1.352 ms Execution time: 182.120 ms Второй авторexplain(analyze, buffers)select m.* from messages m join messages_users u on u.mess_id = m.id where u.user_id = 101678; Hash Join (cost=197351.00..286288.72 rows=36445 width=44) (actual time=2421.834..2514.146 rows=31620 loops=1) Hash Cond: (u.mess_id = m.id) Buffers: shared hit=77644 dirtied=2 -> Index Scan using messages_users_user_id_idx on messages_users u (cost=0.56..88209.38 rows=36445 width=4) (actual time=0.058..69.154 rows=31620 loops=1) Index Cond: (user_id = 101678) Buffers: shared hit=19482 dirtied=2 -> Hash (cost=120021.86..120021.86 rows=6186286 width=44) (actual time=2392.010..2392.010 rows=6186564 loops=1) Buckets: 8388608 Batches: 1 Memory Usage: 548862kB Buffers: shared hit=58159 -> Seq Scan on messages m (cost=0.00..120021.86 rows=6186286 width=44) (actual time=0.018..576.936 rows=6186564 loops=1) Buffers: shared hit=58159 Planning time: 1.023 ms Execution time: 2569.791 ms По первому пользователю с ид 140777 писем больше 31920, по второму с ид 101678 меньше 31620 писем. Но второй запрос идет по Seq Scan ... |
|||
:
Нравится:
Не нравится:
|
|||
03.08.2020, 15:48 |
|
seq_scan при подходящей для индекса селективности
|
|||
---|---|---|---|
#18+
Павел Лузанов kliff Select t2.* FROM t1 JOIN t2 on t2.id=t1.t2_id WHERE t1.id = 5358; Можете поменять условие в тексте запроса: Select t2.* FROM t1 JOIN t2 on t2.id=t1.t2_id WHERE t2 .id = 5358; ? Скорее всего дело в неправильной оценке n_distinct для столбца t1.id. Что показывает: select n_distinct from pg_stats where tablename = 't1' and attname = 'id'; всего 40млн записей, select n_distinct from pg_stats показывает 8500 ... |
|||
:
Нравится:
Не нравится:
|
|||
03.08.2020, 15:50 |
|
seq_scan при подходящей для индекса селективности
|
|||
---|---|---|---|
#18+
Павел Лузанов kliff Select t2.* FROM t1 JOIN t2 on t2.id=t1.t2_id WHERE t1.id = 5358; Можете поменять условие в тексте запроса: Select t2.* FROM t1 JOIN t2 on t2.id=t1.t2_id WHERE t2 .id = 5358; ? Скорее всего дело в неправильной оценке n_distinct для столбца t1.id. Что показывает: select n_distinct from pg_stats where tablename = 't1' and attname = 'id'; да Вы правы, для последнего примера записей в messages больше 6млн, select n_distinct from pg_stats выдает '-1' ... |
|||
:
Нравится:
Не нравится:
|
|||
03.08.2020, 15:54 |
|
seq_scan при подходящей для индекса селективности
|
|||
---|---|---|---|
#18+
https://hdb.docs.pivotal.io/210/hawq/reference/catalog/pg_stats.html Написано, что для столбца с уникальным ключом n_distinct = -1. То есть это нормально ... |
|||
:
Нравится:
Не нравится:
|
|||
03.08.2020, 15:59 |
|
seq_scan при подходящей для индекса селективности
|
|||
---|---|---|---|
#18+
Как видно по explain - у планировщика вполне корректная картина мира о распределении данных, разница не на порядки. На seqscan переключается потому что, согласно настройкам стоимости операций, план с seqscan получается дешевле. См. заодно effective_cache_size Кстати, postgresql 12.5 ещё не существует. ... |
|||
:
Нравится:
Не нравится:
|
|||
03.08.2020, 16:11 |
|
seq_scan при подходящей для индекса селективности
|
|||
---|---|---|---|
#18+
kliff всего 40млн записей, select n_distinct from pg_stats показывает 8500 Разница на несколько порядков. Так всё-таки, можете поменять условие запроса с t1.id = 5358 на t2.id = 5358; ? ... |
|||
:
Нравится:
Не нравится:
|
|||
03.08.2020, 16:55 |
|
seq_scan при подходящей для индекса селективности
|
|||
---|---|---|---|
#18+
Проверьте нет ли тех id с которыми запрос работвет быстро в этом списке: select most_common_vals from pg_stats where tablename = 't1' and attname = 'id'; ... |
|||
:
Нравится:
Не нравится:
|
|||
03.08.2020, 17:00 |
|
seq_scan при подходящей для индекса селективности
|
|||
---|---|---|---|
#18+
Melkij Как видно по explain - у планировщика вполне корректная картина мира о распределении данных, разница не на порядки. На seqscan переключается потому что, согласно настройкам стоимости операций, план с seqscan получается дешевле. См. заодно effective_cache_size Кстати, postgresql 12.5 ещё не существует. Да, извиняюсь. 12.3 стоит. То есть в одном случае id в таблице message в одной или нескольких секциях индекса, а во втором случае id так разбросаны, что нет смысла юзать индекс? Что можно предпринять в таком случае? - Добавить какой то доп. признак в виде даты например? ... |
|||
:
Нравится:
Не нравится:
|
|||
03.08.2020, 17:32 |
|
seq_scan при подходящей для индекса селективности
|
|||
---|---|---|---|
#18+
Павел Лузанов kliff всего 40млн записей, select n_distinct from pg_stats показывает 8500 Разница на несколько порядков. Так всё-таки, можете поменять условие запроса с t1.id = 5358 на t2.id = 5358; ? Тогда запрос потеряет смысл. t2.id мне неизвестны, они получаются из t1 ... |
|||
:
Нравится:
Не нравится:
|
|||
03.08.2020, 17:33 |
|
seq_scan при подходящей для индекса селективности
|
|||
---|---|---|---|
#18+
Павел Лузанов Проверьте нет ли тех id с которыми запрос работвет быстро в этом списке: select most_common_vals from pg_stats where tablename = 't1' and attname = 'id'; есть и те, с которыми быстро и с которыми медленно ... |
|||
:
Нравится:
Не нравится:
|
|||
03.08.2020, 17:44 |
|
seq_scan при подходящей для индекса селективности
|
|||
---|---|---|---|
#18+
kliff 30500 от 6ти млн это же меньше 1% , селективность для использования индекса хорошая, почему тогда оптимизатор выбирает seq_sqan? В какую сторону копать? Подбирать настройки сервера? Заранее спасибо. Покажите ваши настройки на предмет random_page_cost seq_page_cost effective_cache_size потому что цена с т.з. планировщика explain(analyze, buffers) для u.user_id = 140777 и для u.user_id = 101678 фактически одинакова статистика одинакова (и корректна) а скорость hash join сильно ниже (точнее скорость nested loop сильно выше чем база ожидает). из этого следует что у вас настройки базы неверные относительно реальности... отсюда и неверные планы. Ровно тоже обсуждалось парой тем назад под заголовком "Планировщик выбирает seq_scan" на этом же форуме. -- Maxim Boguk лучшая поддержка PostgreSQL: dataegret.ru ... |
|||
:
Нравится:
Не нравится:
|
|||
03.08.2020, 19:07 |
|
seq_scan при подходящей для индекса селективности
|
|||
---|---|---|---|
#18+
Maxim Boguk kliff 30500 от 6ти млн это же меньше 1% , селективность для использования индекса хорошая, почему тогда оптимизатор выбирает seq_sqan? В какую сторону копать? Подбирать настройки сервера? Заранее спасибо. Покажите ваши настройки на предмет random_page_cost seq_page_cost effective_cache_size потому что цена с т.з. планировщика explain(analyze, buffers) для u.user_id = 140777 и для u.user_id = 101678 фактически одинакова статистика одинакова (и корректна) а скорость hash join сильно ниже (точнее скорость nested loop сильно выше чем база ожидает). из этого следует что у вас настройки базы неверные относительно реальности... отсюда и неверные планы. Ровно тоже обсуждалось парой тем назад под заголовком "Планировщик выбирает seq_scan" на этом же форуме. -- Maxim Boguk лучшая поддержка PostgreSQL: dataegret.ru У меня очевидно стоят умолчательные настройки, руками их после установки СУБД никто не менял #seq_page_cost = 1.0 # measured on an arbitrary scale #random_page_cost = 4.0 # same scale as above #cpu_tuple_cost = 0.01 # same scale as above #cpu_index_tuple_cost = 0.005 # same scale as above #cpu_operator_cost = 0.0025 # same scale as above #effective_cache_size = 4GB То есть они закомментированы. Да, ту тему я читал. Пробовал менять настройки. Единственное, может я неверно их менял, потому что никакого результата не получил. То есть я в одной сессии выполнял SET random_page_cost = val; SET seq_page_cost = val; explain(analyze, buffers)select... Но я не нашел, как посмотреть текущие параметры сессии, установились ли эти значения таким образом. ... |
|||
:
Нравится:
Не нравится:
|
|||
03.08.2020, 19:49 |
|
seq_scan при подходящей для индекса селективности
|
|||
---|---|---|---|
#18+
kliffТогда запрос потеряет смысл. t2.id мне неизвестны, они получаются из t1 Это я не внимательно на исходный вопрос посмотрел. Думал, что условие соединения t1.id = t2.id, поэтому замена выглядела эквивалентной. Посмотрел внимательнее. Вы уверены, что ниже приведен план именно этого запроса? kliff explain(analyze, buffers)select m.* from messages m join messages_users u on u.mess_id = m.id where u.user_id = 140777; Nested Loop (cost=1.00..253328.46 rows=29696 width=44) (actual time=0.078..180.555 rows=31920 loops=1) Buffers: shared hit=143395 -> Index Scan using messages_users_user_id_idx on messages_users u (cost=0.56..72884.30 rows=29696 width=4) (actual time=0.061..80.524 rows=31920 loops=1) Index Cond: (user_id = 140777) Buffers: shared hit=15548 -> Index Scan using pk_rep_messages on rep_messages m (cost=0.43..6.07 rows=1 width=44) (actual time=0.003..0.003 rows=1 loops=31920) Index Cond: (id = u.mess_id) Buffers: shared hit=127847 Planning time: 1.352 ms Execution time: 182.120 ms ... |
|||
:
Нравится:
Не нравится:
|
|||
03.08.2020, 19:53 |
|
seq_scan при подходящей для индекса селективности
|
|||
---|---|---|---|
#18+
Павел Лузанов kliffТогда запрос потеряет смысл. t2.id мне неизвестны, они получаются из t1 Это я не внимательно на исходный вопрос посмотрел. Думал, что условие соединения t1.id = t2.id, поэтому замена выглядела эквивалентной. Посмотрел внимательнее. Вы уверены, что ниже приведен план именно этого запроса? kliff explain(analyze, buffers)select m.* from messages m join messages_users u on u.mess_id = m.id where u.user_id = 140777; Nested Loop (cost=1.00..253328.46 rows=29696 width=44) (actual time=0.078..180.555 rows=31920 loops=1) Buffers: shared hit=143395 -> Index Scan using messages_users_user_id_idx on messages_users u (cost=0.56..72884.30 rows=29696 width=4) (actual time=0.061..80.524 rows=31920 loops=1) Index Cond: (user_id = 140777) Buffers: shared hit=15548 -> Index Scan using pk_messages on messages m (cost=0.43..6.07 rows=1 width=44) (actual time=0.003..0.003 rows=1 loops=31920) Index Cond: (id = u.mess_id) Buffers: shared hit=127847 Planning time: 1.352 ms Execution time: 182.120 ms Хотел укоротить названия, когда тут текст размещал. Да точно это он. rep_ хотел убрать ... |
|||
:
Нравится:
Не нравится:
|
|||
03.08.2020, 20:55 |
|
seq_scan при подходящей для индекса селективности
|
|||
---|---|---|---|
#18+
kliff Maxim Boguk пропущено... Покажите ваши настройки на предмет random_page_cost seq_page_cost effective_cache_size потому что цена с т.з. планировщика explain(analyze, buffers) для u.user_id = 140777 и для u.user_id = 101678 фактически одинакова статистика одинакова (и корректна) а скорость hash join сильно ниже (точнее скорость nested loop сильно выше чем база ожидает). из этого следует что у вас настройки базы неверные относительно реальности... отсюда и неверные планы. Ровно тоже обсуждалось парой тем назад под заголовком "Планировщик выбирает seq_scan" на этом же форуме. -- Maxim Boguk лучшая поддержка PostgreSQL: dataegret.ru У меня очевидно стоят умолчательные настройки, руками их после установки СУБД никто не менял #seq_page_cost = 1.0 # measured on an arbitrary scale #random_page_cost = 4.0 # same scale as above #cpu_tuple_cost = 0.01 # same scale as above #cpu_index_tuple_cost = 0.005 # same scale as above #cpu_operator_cost = 0.0025 # same scale as above #effective_cache_size = 4GB То есть они закомментированы. Да, ту тему я читал. Пробовал менять настройки. Единственное, может я неверно их менял, потому что никакого результата не получил. То есть я в одной сессии выполнял SET random_page_cost = val; SET seq_page_cost = val; explain(analyze, buffers)select... Но я не нашел, как посмотреть текущие параметры сессии, установились ли эти значения таким образом. show random_page_cost; и тд если вы через pgbouncer работаете с базой то set работать не будут (причем непредсказуемым образом не будут). при таких настройках не удивительно что база seq scan считает быстрее... это параметры под кофемолку с старым механическим hdd. по тому что я вижу у вас я бы поставил seq_page_cost = 0.1 # measured on an arbitrary scale random_page_cost = 0.11 # same scale as above effective_cache_size = 90% от памяти на сервере если он выделенный под базу и дальше уже смотреть... 99% что поможет конкретно с этими запросами ... |
|||
:
Нравится:
Не нравится:
|
|||
03.08.2020, 23:07 |
|
seq_scan при подходящей для индекса селективности
|
|||
---|---|---|---|
#18+
Maxim Boguk kliff пропущено... У меня очевидно стоят умолчательные настройки, руками их после установки СУБД никто не менял #seq_page_cost = 1.0 # measured on an arbitrary scale #random_page_cost = 4.0 # same scale as above #cpu_tuple_cost = 0.01 # same scale as above #cpu_index_tuple_cost = 0.005 # same scale as above #cpu_operator_cost = 0.0025 # same scale as above #effective_cache_size = 4GB То есть они закомментированы. Да, ту тему я читал. Пробовал менять настройки. Единственное, может я неверно их менял, потому что никакого результата не получил. То есть я в одной сессии выполнял SET random_page_cost = val; SET seq_page_cost = val; explain(analyze, buffers)select... Но я не нашел, как посмотреть текущие параметры сессии, установились ли эти значения таким образом. show random_page_cost; и тд если вы через pgbouncer работаете с базой то set работать не будут (причем непредсказуемым образом не будут). при таких настройках не удивительно что база seq scan считает быстрее... это параметры под кофемолку с старым механическим hdd. по тому что я вижу у вас я бы поставил seq_page_cost = 0.1 # measured on an arbitrary scale random_page_cost = 0.11 # same scale as above effective_cache_size = 90% от памяти на сервере если он выделенный под базу и дальше уже смотреть... 99% что поможет конкретно с этими запросами Огромное спасибо, помогаете уже не первый раз. Буду читать доку, разбираться в этих настройках дальше. При данных настройках план запроса для 101678 стал идентичным с 140777. Начал использовать индекс. Не очень понятно только каким образом тогда вести разработку на постгрис. Разработка обычно ведется на тесте, тест в большинстве случаев на порядок слабее по ресурсам, чем продуктив. Чтобы выжать максимум скорости, тестовый должен быть идентичен боевому с соответствующими настройками СУБД иначе после переноса запросы будут работать не так, как планировалось. Разница конечно очень существенная, раньше по пользователю с 400тыс писем выборка длилась 8 секунд, теперь 0.7 секунды. В районе 450тыс писем, запрос начинает работать без индекса, но это уже решаемый вопрос. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.08.2020, 07:34 |
|
seq_scan при подходящей для индекса селективности
|
|||
---|---|---|---|
#18+
kliff Не очень понятно только каким образом тогда вести разработку на постгрис. Разработка обычно ведется на тесте, тест в большинстве случаев на порядок слабее по ресурсам, чем продуктив. Чтобы выжать максимум скорости, тестовый должен быть идентичен боевому с соответствующими настройками СУБД иначе после переноса запросы будут работать не так, как планировалось. Разница конечно очень существенная, раньше по пользователю с 400тыс писем выборка длилась 8 секунд, теперь 0.7 секунды. В районе 450тыс писем, запрос начинает работать без индекса, но это уже решаемый вопрос. логично что если у вас стоит вопрос тестирования производительности то тестировать надо на оборудовании и настройках таких же как в production. Это впрочем любой базы касается. И даже это ничего не гарантирует, надо постоянно заниматься анализом того что и как работает на production. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.08.2020, 08:55 |
|
|
start [/forum/topic.php?fid=53&fpage=24&tid=1994545]: |
0ms |
get settings: |
9ms |
get forum list: |
14ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
42ms |
get topic data: |
13ms |
get forum data: |
3ms |
get page messages: |
69ms |
get tp. blocked users: |
2ms |
others: | 279ms |
total: | 439ms |
0 / 0 |