Эффективный запрос таблицы многостраничных Postgres

Я только что изменил мою базу данных, чтобы использовать partitioning в 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) Postgres выполняет полное сканирование индекса главной таблицы и соответствующего раздела и объединяет результаты, сортирует их, а затем применяет лимит. Это занимает слишком много времени.

Я могу исправить это с помощью

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

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

Мой вопрос: есть ли какой-либо намек или синтаксис, который я могу использовать в Postgres 8.2, чтобы предотвратить проверку планировщика запросов полной таблицей, но все же используя простой синтаксис, который относится только к главной таблице?

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

EDIT: У меня включено ограничение ограничения (спасибо @Vinko Vrsalovic)

Ответ 1

У меня была аналогичная проблема, которую я смог исправить, задав условия в 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)

Ответ 2

Вы пробовали исключение Constraint (раздел 5.9.4 в документе, к которому вы привязались)

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

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

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

Вы можете использовать команду EXPLAIN для показать разницу между планом с ограничением_включении и планируйте с ним.

Ответ 3

У меня была та же проблема, и в моем случае это сводилось к двум причинам:

  • У меня был индексированный столбец типа timestamp WITH time zone и ограничение раздела этим столбцом с типом timestamp WITHOUT time zone.

  • После исправления ограничений ANALYZE всех дочерних таблиц было необходимо.

Изменить: еще один бит знаний - важно помнить, что исключение ограничений (которое позволяет PG пропускать сканирование некоторых таблиц на основе ваших критериев разбиения) не работает, цитата: non-immutable function such as CURRENT_TIMESTAMP

У меня были запросы с CURRENT_DATE, и это было частью моей проблемы.