все же, почему постгрес предпочитает индекс по id , а не по дате ?
если явно видно что селективность у последнего выше ?
или я что не так понимаю ?
А covering index по starts_at include(id) не пробовали?
нет, можно попробовать, но мне кажется что это несколько избыточно, попробую конечно но вопрос в том числе почему так ? почему используется индекс по первичному ключу, а не по дате ?
Ну index only всегда душу греет
Потому, что по первичному ключу -- он считает, что starts_at по id распределно равномерно, при этом за те последние два месяца у вас небось процэнтов 5 этой таблицы накопилось, так что его оцэнка -- что каждое двадцатое значение будет большэ указанной даты. Потому чтобы найти id потребуется считать всего-то 20 значений по индэксу, делов-то. Он грубо ошыбается потому, что на самом деле starts_at примерно монотонно зависит от id, и ему приходится перелопачивать 95% индэкса чтобы наткнуться на первый.
Да, число 5% взято с потолка, но там от того, 20%, 5% или треть-процэнта -- суть не меняется, только оцэнки будут 5 значений и 80% индэкс, 20 значений и 95% индэкса или 300 значений и 99.7% индэкса.
как-то не очень понятно ) при большом периоде да, звучит логично, но не когда запрос за пару дней данные берет эт отого у меня и ступор, но стату ему подсунуть попробуем
Можэте подставить реальное вашэ количество данных за два дня, и за всего, и понять, сколько там в итоге работы (реально и по его мнению) в обоих планах.
CREATE INDEX statistics_app_track_starts_at_test2 ON statistics.app_track (starts_at ) include(id) ; помогло уже похоже на решение, но чуется оверхед, попробую еще совет со статистикой
вот же https://t.me/pgsql/334304
Почти уверен, что сработает только для нескольких дней. Попробуйте explain с начала сентября показать.
с включающим индексом ? или что именно ?
Если covering index допустим - я всегда использую возможность пустить запрос не трогая саму таблицу А про странности - думаю у каждого есть что рассказать
Да, с ключающим индэксом. Ну, вы жэ видели его оцэнку с какой-то сентябрьской даты -- cost 40. Сколько строк должно быть в выборке по index-only scan, чтобы было меньшэ? 400? Очевидно, что тот запрос по включающему индэксу не запустится.
проведу тесты со статистикой, вернусь к индексу , а то я его удалил ) сейчас работаю с полным дампом реальных данных, когда найду лучшее решение, буду переносить на прод
А можэте с индэксом показать explain (verbose, analyze) на starts_at>'2021-09-12 07:19:29'; ?
мм, нет смысла смотреть мне кажется добавляю сутки в диапазон, и включающей индекс перестает работать test=# explain SELECT min(id) as MN FROM statistics.app_track WHERE starts_at>'2021-10-11 07:19:29'; QUERY PLAN --------------------------------------------------------------------------------------------------------- Result (cost=729.61..729.62 rows=1 width=4) InitPlan 1 (returns $0) -> Limit (cost=0.44..729.61 rows=1 width=4) -> Index Scan using app_track_pkey on app_track (cost=0.44..61576919.25 rows=84448 width=4) Index Cond: (id IS NOT NULL) Filter: (starts_at > '2021-10-11 07:19:29'::timestamp without time zone) (6 rows) test=# explain SELECT min(id) as MN FROM statistics.app_track WHERE starts_at>'2021-10-12 07:19:29'; QUERY PLAN ----------------------------------------------------------------------------------------------------------------------- Aggregate (cost=440.40..440.41 rows=1 width=4) -> Index Only Scan using statistics_app_track_starts_at_test2 on app_track (cost=0.56..409.42 rows=12392 width=4) Index Cond: (starts_at > '2021-10-12 07:19:29'::timestamp without time zone) (3 rows) хотя фокус с id-0 работает неплохо даже если брать последний месяц
Ну да, понятно, что он гораздо раньшэ перейдёт на ту жэ ошыбку. Я просил 2021-09-12 просто как место, где всё ужэ очевидно будет по-старому.
Обсуждают сегодня