powered by simpleCommunicator - 2.0.52     © 2025 Programmizd 02
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / seq_scan при подходящей для индекса селективности
23 сообщений из 23, страница 1 из 1
seq_scan при подходящей для индекса селективности
    #39986119
kliff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ребят, ткните пожалуйста, где можно что то дельное почитать. Проблема такая.

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? В какую сторону копать? Подбирать настройки сервера?

Заранее спасибо.
...
Рейтинг: 0 / 0
seq_scan при подходящей для индекса селективности
    #39986131
kliff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дальнейшие эксперименты

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
...
Рейтинг: 0 / 0
seq_scan при подходящей для индекса селективности
    #39986133
kliff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
...
Рейтинг: 0 / 0
seq_scan при подходящей для индекса селективности
    #39986134
Melkij
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
explain (analyze) показывайте. Вслепую ощупывать слона конечно увлекательно, не малопродуктивно. И на всякий случай уточните какие у вас seq_page_cost, random_page_cost настроены.
...
Рейтинг: 0 / 0
seq_scan при подходящей для индекса селективности
    #39986136
Павел Лузанов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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';
...
Рейтинг: 0 / 0
seq_scan при подходящей для индекса селективности
    #39986149
kliff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
...
Рейтинг: 0 / 0
seq_scan при подходящей для индекса селективности
    #39986152
kliff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Павел Лузанов
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
...
Рейтинг: 0 / 0
seq_scan при подходящей для индекса селективности
    #39986156
kliff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Павел Лузанов
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'
...
Рейтинг: 0 / 0
seq_scan при подходящей для индекса селективности
    #39986160
kliff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
https://hdb.docs.pivotal.io/210/hawq/reference/catalog/pg_stats.html

Написано, что для столбца с уникальным ключом n_distinct = -1. То есть это нормально
...
Рейтинг: 0 / 0
seq_scan при подходящей для индекса селективности
    #39986169
Melkij
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как видно по explain - у планировщика вполне корректная картина мира о распределении данных, разница не на порядки.
На seqscan переключается потому что, согласно настройкам стоимости операций, план с seqscan получается дешевле. См. заодно effective_cache_size

Кстати, postgresql 12.5 ещё не существует.
...
Рейтинг: 0 / 0
seq_scan при подходящей для индекса селективности
    #39986186
Павел Лузанов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kliff
всего 40млн записей, select n_distinct from pg_stats показывает 8500

Разница на несколько порядков.

Так всё-таки, можете поменять условие запроса с t1.id = 5358 на t2.id = 5358;
?
...
Рейтинг: 0 / 0
seq_scan при подходящей для индекса селективности
    #39986191
Павел Лузанов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Проверьте нет ли тех id с которыми запрос работвет быстро в этом списке:
select most_common_vals from pg_stats where tablename = 't1' and attname = 'id';
...
Рейтинг: 0 / 0
seq_scan при подходящей для индекса селективности
    #39986201
kliff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Melkij
Как видно по explain - у планировщика вполне корректная картина мира о распределении данных, разница не на порядки.
На seqscan переключается потому что, согласно настройкам стоимости операций, план с seqscan получается дешевле. См. заодно effective_cache_size

Кстати, postgresql 12.5 ещё не существует.

Да, извиняюсь. 12.3 стоит.

То есть в одном случае id в таблице message в одной или нескольких секциях индекса, а во втором случае id так разбросаны, что нет смысла юзать индекс? Что можно предпринять в таком случае? - Добавить какой то доп. признак в виде даты например?
...
Рейтинг: 0 / 0
seq_scan при подходящей для индекса селективности
    #39986202
kliff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Павел Лузанов
kliff
всего 40млн записей, select n_distinct from pg_stats показывает 8500

Разница на несколько порядков.

Так всё-таки, можете поменять условие запроса с t1.id = 5358 на t2.id = 5358;
?


Тогда запрос потеряет смысл. t2.id мне неизвестны, они получаются из t1
...
Рейтинг: 0 / 0
seq_scan при подходящей для индекса селективности
    #39986206
kliff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Павел Лузанов
Проверьте нет ли тех id с которыми запрос работвет быстро в этом списке:
select most_common_vals from pg_stats where tablename = 't1' and attname = 'id';


есть и те, с которыми быстро и с которыми медленно
...
Рейтинг: 0 / 0
seq_scan при подходящей для индекса селективности
    #39986222
Фотография 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
...
Рейтинг: 0 / 0
seq_scan при подходящей для индекса селективности
    #39986236
kliff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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...

Но я не нашел, как посмотреть текущие параметры сессии, установились ли эти значения таким образом.
...
Рейтинг: 0 / 0
seq_scan при подходящей для индекса селективности
    #39986238
Павел Лузанов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
...
Рейтинг: 0 / 0
seq_scan при подходящей для индекса селективности
    #39986247
kliff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Павел Лузанов
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_ хотел убрать
...
Рейтинг: 0 / 0
seq_scan при подходящей для индекса селективности
    #39986264
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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% что поможет конкретно с этими запросами
...
Рейтинг: 0 / 0
seq_scan при подходящей для индекса селективности
    #39986290
kliff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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тыс писем, запрос начинает работать без индекса, но это уже решаемый вопрос.
...
Рейтинг: 0 / 0
seq_scan при подходящей для индекса селективности
    #39986300
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kliff

Не очень понятно только каким образом тогда вести разработку на постгрис. Разработка обычно ведется на тесте, тест в большинстве случаев на порядок слабее по ресурсам, чем продуктив. Чтобы выжать максимум скорости, тестовый должен быть идентичен боевому с соответствующими настройками СУБД иначе после переноса запросы будут работать не так, как планировалось.

Разница конечно очень существенная, раньше по пользователю с 400тыс писем выборка длилась 8 секунд, теперь 0.7 секунды. В районе 450тыс писем, запрос начинает работать без индекса, но это уже решаемый вопрос.


логично что если у вас стоит вопрос тестирования производительности то тестировать надо на оборудовании и настройках таких же как в production.
Это впрочем любой базы касается.
И даже это ничего не гарантирует, надо постоянно заниматься анализом того что и как работает на production.
...
Рейтинг: 0 / 0
seq_scan при подходящей для индекса селективности
    #39986581
kliff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Maxim Boguk, Спасибо, как всегда все четко и по делу.
...
Рейтинг: 0 / 0
23 сообщений из 23, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / seq_scan при подходящей для индекса селективности
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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