Эффективные запросы таблицы Postgres мультираздела

Я только что реструктурировал свою базу данных для использования разделения в Пост-ГРЭС 8.2. Теперь у меня есть проблема с производительностью запросов:

SELECT *
FROM my_table
WHERE time_stamp >= '2010-02-10' and time_stamp < '2010-02-11'
ORDER BY id DESC
LIMIT 100;

В таблице существует 45 миллионов строк. До разделения это использовало бы обратное индексное сканирование и остановку, как только это поразило предел.

После разделения (на диапазонах time_stamp), Пост-ГРЭС делает полное индексное сканирование основной таблицы и соответствующего раздела и объединяет результаты, сортирует их, затем применяет предел. Это берет слишком долго.

Я могу зафиксировать его с:

SELECT * FROM (
  SELECT *
  FROM my_table_part_a
  WHERE time_stamp >= '2010-02-10' and time_stamp < '2010-02-11'
  ORDER BY id DESC
  LIMIT 100) t
UNION ALL
SELECT * FROM (
  SELECT *
  FROM my_table_part_b
  WHERE time_stamp >= '2010-02-10' and time_stamp < '2010-02-11'
  ORDER BY id DESC
  LIMIT 100) t
UNION ALL
  ... and so on ...
ORDER BY id DESC
LIMIT 100

Это работает быстро. Разделы, где штампы времен из диапазона, даже не включены в план запросов.

Мой вопрос: Есть ли некоторая подсказка или синтаксис, который я могу использовать в Пост-ГРЭС 8.2, чтобы препятствовать тому, чтобы планировщик запроса сканировал полную таблицу, но все еще использовал простой синтаксис, который только относится к основной таблице?

В основном я могу избежать боли динамичного создания большого Запроса на объединение по каждому разделу, который, оказывается, в настоящее время определяется?

Править: У меня есть включенный constraint_exclusion (благодарит @Vinko Vrsalovic),

11
задан Adrian Pronk 10 February 2010 в 12:50
поделиться

2 ответа

Пытались ли вы попробовать Исключение ограничений (раздел 5.9.4 в документе, на который вы ссылаетесь)

Исключение ограничений - запрос метод оптимизации, который улучшает производительность для таблиц разделов определённым образом наверху. В качестве примера:

 SET constraint_exclusion = on; 
 SELECT count(*) FROM measurement WHERE logdate >= DATE '2006-01-01'; 

Без исключение ограничения, вышеприведенный запрос сканировал бы каждый из разделов таблицу измерений. С ограничением исключение включено, планировщик будет рассматривать ограничения каждого разделить и попытаться доказать, что раздел не нужно сканировать, потому что он не мог содержать никаких встреч рядов запрос - это пункт "ГДЕ". Когда планировщик может это доказать, это исключает раздел из плана запроса.

Команду EXPLAIN можно использовать, чтобы показать разницу между планом с ограничением_исключением и планировать с этим.

5
ответ дан 3 December 2019 в 09:20
поделиться

У меня была похожая проблема, которую я смог решить путем приведения условий в WHERE. EG: (при условии, что столбец time_stamp имеет тип timestamptz)

WHERE time_stamp >= '2010-02-10'::timestamptz and time_stamp < '2010-02-11'::timestamptz

Также убедитесь, что условие CHECK в таблице определено таким же образом... ЭГ: CHECK (time_stamp < '2010-02-10'::timestamptz)

4
ответ дан 3 December 2019 в 09:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: