SELECT min(id) as MN FROM statistics.app_track WHERE starts_at>='2021-09-20 07:19:29';
имеется индекс на соответствующее поле, но запрос выполняется неожиданно долго (даже если дату сдвинуть на день назад от сейчас)
експлейн говорит следующее :
Result (cost=39.44..39.45 rows=1 width=4)
InitPlan 1 (returns $0)
-> Limit (cost=0.44..39.44 rows=1 width=4)
-> Index Scan using app_track_pkey on app_track (cost=0.44..61175133.00 rows=1568476 width=4)
Index Cond: (id IS NOT NULL)
Filter: (starts_at >= '2021-09-20 07:19:29'::timestamp without time zone)
то есть запрос использует первичный ключ, а не индекс по дате
в то время как запрос
with result as
( SELECT id as MN FROM statistics.app_track WHERE starts_at>='2021-10-4 07:19:29' )
select min(MN) from result as MN
работает по индексу по дате и результат выдает почти моментально,
но использовать нужно первый вариант, технические ограничения
пробовал выполнить реиндендекс индекса по дате, анализ таблицы, даже снял дамп данных (40Г) и восстановил на другой хост с этой же схемой (эмулировал вакуумфул, так сказать), не помогло, план запроса не меняется
может кто проконсультировать, почему выбирается такой план, и можно ли с этим как-то побороться ?
Попробуйте вариант с order by mn limit 1
на главное не повлияло test=# explain SELECT min(id) as MN FROM statistics.app_track WHERE starts_at>='2021-09-20' order by mn limit 1 ; QUERY PLAN ----------------------------------------------------------------------------------------------------------- Limit (cost=38.76..38.76 rows=1 width=4) InitPlan 1 (returns $0) -> Limit (cost=0.44..38.74 rows=1 width=4) -> Index Scan using app_track_pkey on app_track (cost=0.44..61175133.00 rows=1597229 width=4) Index Cond: (id IS NOT NULL) Filter: (starts_at >= '2021-09-20 00:00:00'::timestamp without time zone) -> Sort (cost=38.76..38.76 rows=1 width=4) Sort Key: ($0) -> Result (cost=38.74..38.75 rows=1 width=4) (9 rows)
Уберите min(), она заменяется на то что предложено
Я бы предложыл обновить postgres, это ошыбка планировщика какая-то. Настолько грубая, что она ужэ должна быть давно исправлена.
psql (13.4 (Ubuntu 13.4-4.pgdg20.04+1))
Не, значит что-то ещё не то.
А, туплю, это жэ не min(дата), ё-моё. Ладно, тренировочка чтобы проснуться, да.
Ну, то есть, ошыбка есть -- но не такая ужасная, как я подумал. Можно попробовать коррелированную статистику (id, starts_at) добавить. https://www.postgresql.org/docs/13/planner-stats.html#PLANNER-STATS-EXTENDED
почитаю, попробую, но пока индекс с инклуд создается )
И да, альтэрнатива у него -- считать все значения по указанной дате и отсортировать по id. Это. понятно, много работы, какие-то, видимо, десятки или сотни тысяч строк (не знаю, сколько у вас там реально).
все правильно ? test=# CREATE STATISTICS statistics.statistics_app_track_stat_on_starts_at_and_id (dependencies) ON starts_at, id FROM statistics.app_track; CREATE STATISTICS test=# explain SELECT min(id) as MN FROM statistics.app_track WHERE starts_at>'2021-09-12 07:19:29'; QUERY PLAN ----------------------------------------------------------------------------------------------------------- Result (cost=28.46..28.47 rows=1 width=4) InitPlan 1 (returns $0) -> Limit (cost=0.44..28.46 rows=1 width=4) -> Index Scan using app_track_pkey on app_track (cost=0.44..61262227.80 rows=2186085 width=4) Index Cond: (id IS NOT NULL) Filter: (starts_at > '2021-09-12 07:19:29'::timestamp without time zone) (6 rows) test=# analyze statistics.app_track; ANALYZE test=# explain SELECT min(id) as MN FROM statistics.app_track WHERE starts_at>'2021-09-12 07:19:29'; QUERY PLAN ----------------------------------------------------------------------------------------------------------- Result (cost=29.85..29.86 rows=1 width=4) InitPlan 1 (returns $0) -> Limit (cost=0.44..29.85 rows=1 width=4) -> Index Scan using app_track_pkey on app_track (cost=0.44..61507309.35 rows=2091089 width=4) Index Cond: (id IS NOT NULL) Filter: (starts_at > '2021-09-12 07:19:29'::timestamp without time zone) (6 rows) если, то не помогло (
ndistinct, dependencies на pkey вообще безсмысленнен по-моему.
И размеры статистики можно попинать. statistic_target там увеличить.
Обсуждают сегодня