Работает ли обрезка разделов в Postgres 11 для операторов Update - PullRequest
0 голосов
/ 28 ноября 2018

Я недавно начал использовать postgresql 11 и столкнулся с одним интересным поведением.

Я создал таблицу "преобразований" с разделами (logdate - это ключ).

CREATE TABLE conversions(
  .....
  logdate timestamp without time zone,
  ....
) PARTITION BY RANGE (logdate);
CREATE INDEX ON conversions(logdate);
--
CREATE unique INDEX conversions_log_id_idx ON conversions(logdate, id);
CREATE INDEX conversions_log_is_created_idx ON conversions(logdate, is_created);

Сокращение раздела работает для операторов SELECT (как описано в документации):

SELECT *
      FROM conversions
WHERE logdate BETWEEN to_date('2017-09-01 00:00:00','YYYY-MM-DD HH24:MI:SS') AND to_date('2017-09-08 23:59:59','YYYY-MM-DD HH24:MI:SS');


"Append  (cost=0.42..11134.74 rows=13051 width=1715)"
"  Subplans Removed: 12"
"  ->  Index Scan using conversions_y2017q03_logdate_idx on conversions_y2017q03  (cost=0.42..10962.37 rows=13038 width=1715)"
"        Index Cond: ((logdate >= to_date('2017-09-01 00:00:00'::text, 'YYYY-MM-DD HH24:MI:SS'::text)) AND (logdate <= to_date('2017-09-08 23:59:59'::text, 'YYYY-MM-DD HH24:MI:SS'::text)))"
"  ->  Index Scan using conversions_default_logdate_is_created_idx on conversions_default  (cost=0.14..8.16 rows=1 width=2030)"
"        Index Cond: ((logdate >= to_date('2017-09-01 00:00:00'::text, 'YYYY-MM-DD HH24:MI:SS'::text)) AND (logdate <= to_date('2017-09-08 23:59:59'::text, 'YYYY-MM-DD HH24:MI:SS'::text)))"

Это работает хорошо, вы можете видеть это раньше.

Но это не работает для операторов обновления.

Например:

UPDATE conversions
  SET is_created = 'N'
WHERE logdate BETWEEN to_date('2017-09-01 00:00:00','YYYY-MM-DD HH24:MI:SS') AND to_date('2017-09-08 23:59:59','YYYY-MM-DD HH24:MI:SS')

"Update on conversions  (cost=0.42..11069.48 rows=13051 width=1727)"
"  Update on conversions_y2016q04"
"  Update on conversions_y2017q01"
"  Update on conversions_y2017q02"
"  Update on conversions_y2017q03"
"  Update on conversions_y2017q04"
"  Update on conversions_y2018q01"
"  Update on conversions_y2018q02"
"  Update on conversions_y2018q03"
"  Update on conversions_y2018q04"
"  Update on conversions_y2019q01"
"  Update on conversions_y2019q02"
"  Update on conversions_y2019q03"
"  Update on conversions_y2019q04"
"  Update on conversions_default"
"  ->  Index Scan using conversions_y2016q04_logdate_is_created_idx on conversions_y2016q04  (cost=0.42..8.44 rows=1 width=1661)"
"        Index Cond: ((logdate >= to_date('2017-09-01 00:00:00'::text, 'YYYY-MM-DD HH24:MI:SS'::text)) AND (logdate <= to_date('2017-09-08 23:59:59'::text, 'YYYY-MM-DD HH24:MI:SS'::text)))"
"  ->  Index Scan using conversions_y2017q01_logdate_is_created_idx on conversions_y2017q01  (cost=0.42..8.45 rows=1 width=1804)"
"        Index Cond: ((logdate >= to_date('2017-09-01 00:00:00'::text, 'YYYY-MM-DD HH24:MI:SS'::text)) AND (logdate <= to_date('2017-09-08 23:59:59'::text, 'YYYY-MM-DD HH24:MI:SS'::text)))"
"  ->  Index Scan using conversions_y2017q02_logdate_is_created_idx on conversions_y2017q02  (cost=0.42..8.45 rows=1 width=1805)"
"        Index Cond: ((logdate >= to_date('2017-09-01 00:00:00'::text, 'YYYY-MM-DD HH24:MI:SS'::text)) AND (logdate <= to_date('2017-09-08 23:59:59'::text, 'YYYY-MM-DD HH24:MI:SS'::text)))"
"  ->  Index Scan using conversions_y2017q03_logdate_idx on conversions_y2017q03  (cost=0.42..10962.37 rows=13038 width=1727)"
"        Index Cond: ((logdate >= to_date('2017-09-01 00:00:00'::text, 'YYYY-MM-DD HH24:MI:SS'::text)) AND (logdate <= to_date('2017-09-08 23:59:59'::text, 'YYYY-MM-DD HH24:MI:SS'::text)))"
"  ->  Index Scan using conversions_y2017q04_logdate_id_idx on conversions_y2017q04  (cost=0.29..8.31 rows=1 width=1699)"
"        Index Cond: ((logdate >= to_date('2017-09-01 00:00:00'::text, 'YYYY-MM-DD HH24:MI:SS'::text)) AND (logdate <= to_date('2017-09-08 23:59:59'::text, 'YYYY-MM-DD HH24:MI:SS'::text)))"
"  ->  Index Scan using conversions_y2018q01_logdate_is_created_idx on conversions_y2018q01  (cost=0.14..8.16 rows=1 width=2036)"
"        Index Cond: ((logdate >= to_date('2017-09-01 00:00:00'::text, 'YYYY-MM-DD HH24:MI:SS'::text)) AND (logdate <= to_date('2017-09-08 23:59:59'::text, 'YYYY-MM-DD HH24:MI:SS'::text)))"
"  ->  Index Scan using conversions_y2018q02_logdate_is_created_idx on conversions_y2018q02  (cost=0.14..8.16 rows=1 width=2036)"
"        Index Cond: ((logdate >= to_date('2017-09-01 00:00:00'::text, 'YYYY-MM-DD HH24:MI:SS'::text)) AND (logdate <= to_date('2017-09-08 23:59:59'::text, 'YYYY-MM-DD HH24:MI:SS'::text)))"
"  ->  Index Scan using conversions_y2018q03_logdate_is_created_idx on conversions_y2018q03  (cost=0.14..8.16 rows=1 width=2036)"
"        Index Cond: ((logdate >= to_date('2017-09-01 00:00:00'::text, 'YYYY-MM-DD HH24:MI:SS'::text)) AND (logdate <= to_date('2017-09-08 23:59:59'::text, 'YYYY-MM-DD HH24:MI:SS'::text)))"
"  ->  Index Scan using conversions_y2018q04_logdate_is_created_idx on conversions_y2018q04  (cost=0.14..8.16 rows=1 width=2036)"
"        Index Cond: ((logdate >= to_date('2017-09-01 00:00:00'::text, 'YYYY-MM-DD HH24:MI:SS'::text)) AND (logdate <= to_date('2017-09-08 23:59:59'::text, 'YYYY-MM-DD HH24:MI:SS'::text)))"
"  ->  Index Scan using conversions_y2019q01_logdate_is_created_idx on conversions_y2019q01  (cost=0.14..8.16 rows=1 width=2036)"
"        Index Cond: ((logdate >= to_date('2017-09-01 00:00:00'::text, 'YYYY-MM-DD HH24:MI:SS'::text)) AND (logdate <= to_date('2017-09-08 23:59:59'::text, 'YYYY-MM-DD HH24:MI:SS'::text)))"
"  ->  Index Scan using conversions_y2019q02_logdate_is_created_idx on conversions_y2019q02  (cost=0.14..8.16 rows=1 width=2036)"
"        Index Cond: ((logdate >= to_date('2017-09-01 00:00:00'::text, 'YYYY-MM-DD HH24:MI:SS'::text)) AND (logdate <= to_date('2017-09-08 23:59:59'::text, 'YYYY-MM-DD HH24:MI:SS'::text)))"
"  ->  Index Scan using conversions_y2019q03_logdate_is_created_idx on conversions_y2019q03  (cost=0.14..8.16 rows=1 width=2036)"
"        Index Cond: ((logdate >= to_date('2017-09-01 00:00:00'::text, 'YYYY-MM-DD HH24:MI:SS'::text)) AND (logdate <= to_date('2017-09-08 23:59:59'::text, 'YYYY-MM-DD HH24:MI:SS'::text)))"
"  ->  Index Scan using conversions_y2019q04_logdate_is_created_idx on conversions_y2019q04  (cost=0.14..8.16 rows=1 width=2036)"
"        Index Cond: ((logdate >= to_date('2017-09-01 00:00:00'::text, 'YYYY-MM-DD HH24:MI:SS'::text)) AND (logdate <= to_date('2017-09-08 23:59:59'::text, 'YYYY-MM-DD HH24:MI:SS'::text)))"
"  ->  Index Scan using conversions_default_logdate_is_created_idx on conversions_default  (cost=0.14..8.16 rows=1 width=2036)"
"        Index Cond: ((logdate >= to_date('2017-09-01 00:00:00'::text, 'YYYY-MM-DD HH24:MI:SS'::text)) AND (logdate <= to_date('2017-09-08 23:59:59'::text, 'YYYY-MM-DD HH24:MI:SS'::text)))"

Похоже, что Postgresql использует индекс для поиска необходимых разделов.

Это хорошее поведение?Вы мысли?

1 Ответ

0 голосов
/ 03 декабря 2018

Используете ли вы подготовленные заявления?Если это так, можно использовать общий план, что означает, что планировщик не сможет выполнять сокращение, поскольку значения, необходимые для этого, будут доступны только при выполнении общего плана.SELECT поддерживает сокращение времени выполнения начиная с PostgreSQL 11, поэтому все в порядке, даже если планировщик не может выполнить сокращение в своем случае.Однако для UPDATE только планировщик может выполнять обрезку, поэтому его нет, если используется общий план.Я подозревал, что вы, возможно, используете подготовленное утверждение, потому что, глядя на вывод объяснения SELECT, представленный в вопросе:

"Append  (cost=0.42..11134.74 rows=13051 width=1715)"
"  Subplans Removed: 12"

ясно, что сокращение времени выполнения выполняетсяиспользуемый.Подробнее о сокращении разделов читайте здесь:

https://www.postgresql.org/docs/devel/ddl-partitioning.html#DDL-PARTITION-PRUNING

РЕДАКТИРОВАТЬ: Я хотел бы также упомянуть, что UPDATE может использовать сокращение, если планировщик получает изменения, чтобы сделать это (не общий план)при условии, что вы используете LIST и RANGE разбиение (не работает с HASH, что является новым в PostgreSQL 11).

РЕДАКТИРОВАТЬ 2: Как уже упоминалось в комментарии, это, похоже, должносделать с тем фактом, что OP использует в предложении where функцию to_date, которая делает сравниваемое выражение неизменным с точки зрения PostgreSQL.Это означает, что планировщик не может выполнить сокращение с ним, хотя исполнитель может, потому что это все еще устойчивое выражение.Как я уже говорил выше, обрезка для исполнителя не поддерживается для ОБНОВЛЕНИЙ.

...