Scan using purchase_status_change_idx on purchase (cost=0.44..13816.52 rows=36 width=44) (actual time=0.075..420.762 rows=51539 loops=1)
смотрю статистику по этому полю
reltuples | 9.05529e+06
select array_length(histogram_bounds,1) from pg_stats where tablename = 'purchase' and attname = 'change_status_date';
array_length
--------------
101
соответственно
select 9.05529e+06 / 101;
?column?
--------------------
89656.336633663366
и это значение похоже на правду.
Но почему планировщик считает rows=36 ?
А почему /100 ? Это только 100 самых частых значений. Вашэ значение индэкса в них, видимо, непопадает. Про остальных -- я дажэ не знаю, откуда он берёт оцэнку количества, но в общем, если допустимтам всего различных значений около 500 000 -- то логично предположыть, что большынство непопавшых в статистику будет выдавать порядка 2E7/5E5 ~ 40 строк.
А что реально среди этих 500 000 значений есть те, которые чуть-чуть непопали в статистику (то есть которых десятки тысяч) и те, которых считанные штуки или вообще одно -- ну, так это средняя температура по больницэ.
101 это количество чанков в гистограмме, по идеи в каждом чанке примерно равное кол. строк histogram_bounds - Список значений, разделяющих значения столбца на примерно одинаковые популяции.
Ну, смотрит-то он на elem_count_чототам.
В моем случае он пустой
Вообще, эта histogram -- это только bounds. То есть от такого-то до такое-то значение будет да, сколько-то десятков тысяч (там ещё выкидываются most_common, так что не очень понятно, сколько. Но десятки тысяч, скорее всего). А для любого одного конкретного внутри этого -- в среднем гораздо меньшэ. Насколько... Зависит от их количества там, между bounds.
так у меня условие change_status_date >= now() - '3 day' ::interval и планировщик должен посмотреть какое кол. чанков попадает под условие и их сумма будет предполагаемым значением. Но как он умудряется 36 строк определить я не понимаю.
И что там конкретно в histogram_bounds соответствует этому условию?
Вообще, глупо было начинать обсуждение плана запроса без 303899.
Что конкретно в histogram_bounds соответствует этому условию?
select right(histogram_bounds::text,60) from pg_stats where tablename = 'purchase' and attname = 'change_status_date'; right -------------------------------------------------------------- ","2023-05-12 03:21:27.422117","2023-05-17 07:15:44.718477"} соответственно "2023-05-17 07:15:44.718477" он же последний на текущий момент
Крайние значения в гистограмме, похоже, не учитываются, т.к. generic_restriction_selectivity() передает n_skip = 1 в histogram_selectivity() https://github.com/postgres/postgres/blob/master/src/backend/utils/adt/selfuncs.c#L866
Да, он, похожэ, считает это значение за максимум. Почему у меня тожэ выкинуто несколько малозначимых крайних значений -- я пока что непонимаю (Никита пытается объяснить). Но -- скорее всего, статистика последний раз собиралась, когда ничего после 12-го числа не было, потому он и считает, что за эти три дня (16-19, да?) (или 14-17?) -- у него ничего или почти ничего нет.
я ее вчера руками запускал, и сейчас запустил
А, да, у тебя вроде действительно там 17-м оканчивается, что-то я не туда посмотрел.
Выглядит как какая-то ошыбка.
Мне кажется, что последний диапазон гистограммы оказывается неполным, т.к. граница поискового диапазона попадает в его середину, поэтому он и не учитывается.
Что само по себе (насчёт середины) выглядит странным, вроде границы должны быть границами. И, в любом случае -- ну, поделили бы на 2 estimate... А вот так, выкидывать оба экстремума из оцэнок и брать им значения просто с потолка...
https://www.pvsm.ru/postgresql/256486
Обсуждают сегодня