#postgresql #partitioning
#postgresql #разделение на разделы
Вопрос:
Я использую Postgres 13 и создал таблицу со столбцами A, B и C. Таблица разделена символом A с 2 возможными значениями. Раздел 1 содержит 100 возможных значений для B и C, в то время как раздел 2 имеет 100 совершенно разных значений для B и 1 другое значение для C. Я установил статистику для обоих столбцов на максимум, чтобы это определенно не вызывало никаких проблем
Если я группирую по B и C в любом разделе, Postgres правильно оценивает количество групп. Однако, если я выполняю запрос к базовой таблице, где я действительно этого хочу, он оценивает, как я предполагаю, отсутствие функциональной зависимости между A, B и C, т.Е. (p1B p1C) * (p2B p2C) для 200 * 101, в отличие от реальности p1B * p1C p2B *p2C для 10000 100.
Наверное, я наполовину ожидал, что он будет суммировать базовые разделы, а не использовать полное количество 200 B и 101 C, которые может видеть базовая таблица. Более того, если я также добавлю A в группу к тому времени, оценка ошибочно удваивается еще больше, так как тогда она думает, что этот набор также будет дублироваться для каждого значения A.
Все это заставило меня подумать, что мне нужна расширенная статистика, чтобы сказать, что A влияет либо на B, либо на C, либо на оба. Однако, если я установлю его в базовом разделе и проанализирую, значение в pg_statistic_ext_data->stxdndistinct равно нулю. Принимая во внимание, что если я установлю его на самих разделах, это, похоже, сработает, хотя и не особенно полезно, потому что оценка уже верна на этом уровне. Как мне добиться корректной оценки Postgres по базовой таблице без необходимости запускать запрос ко всем разделам и объединять их вместе?
Ответ №1:
Вы можете определить расширенную статистику для разделенной таблицы, но в этом случае PostgreSQL не собирает никаких данных. Вам нужно будет создать расширенную статистику по всем разделам по отдельности.
Вы можете подтвердить это, запросив собранные данные после ANALYZE
:
SELECT s.stxrelid::regclass AS table_name,
s.stxname AS statistics_name,
d.stxdndistinct AS ndistinct,
d.stxddependencies AS dependencies
FROM pg_statistic_ext AS s
JOIN pg_statistic_ext_data AS d
ON d.stxoid = s.oid;
Здесь, безусловно, есть возможности для улучшения; возможно, в первую очередь не разрешать определять расширенную статистику для разделенной таблицы.
Комментарии:
1. » возможно, в первую очередь не разрешайте определять расширенную статистику для секционированной таблицы » — или даже лучше: распределите ее по всем разделам 😉 точно так же, как индексы
Ответ №2:
Я обнаружил, что мне просто нужно включить enable_partitionwise_aggregate, чтобы получить правильную оценку