Ich habe eine große Tabelle in Postgres.Postgres Partition Beschneiden
Der Tabellenname ist bigtable
und die Spalten sind:
integer |timestamp |xxx |xxx |...|xxx
category_id|capture_time|col1|col2|...|colN
ich partitioniert haben in der Tabelle auf Modulo 10 von category_id und das Datum Teil der capture_time Spalte.
Die Partitionstabellen wie folgt aussehen:
CREATE TABLE myschema.bigtable_d000h0(
CHECK (category_id%10=0 AND capture_time >= DATE '2012-01-01' AND capture_time < DATE '2012-01-02')
) INHERITS (myschema.bigtable);
CREATE TABLE myschema.bigtable_d000h1(
CHECK (category_id%10=1 AND capture_time >= DATE '2012-01-01' AND capture_time < DATE '2012-01-02')
) INHERITS (myschema.bigtable);
Wenn ich eine Abfrage mit category_id und capture_time in der where-Klausel ausführen, werden die Partitionen nicht wie erwartet zurückgeschnitten.
explain select * from bigtable where capture_time >= '2012-01-01' and capture_time < '2012-01-02' and category_id=100;
"Result (cost=0.00..9476.87 rows=1933 width=216)"
" -> Append (cost=0.00..9476.87 rows=1933 width=216)"
" -> Seq Scan on bigtable (cost=0.00..0.00 rows=1 width=210)"
" Filter: ((capture_time >= '2012-01-01 00:00:00'::timestamp without time zone) AND (capture_time < '2012-01-02 00:00:00'::timestamp without time zone) AND (category_id = 100))"
" -> Seq Scan on bigtable_d000h0 bigtable (cost=0.00..1921.63 rows=1923 width=216)"
" Filter: ((capture_time >= '2012-01-01 00:00:00'::timestamp without time zone) AND (capture_time < '2012-01-02 00:00:00'::timestamp without time zone) AND (category_id = 100))"
" -> Seq Scan on bigtable_d000h1 bigtable (cost=0.00..776.93 rows=1 width=218)"
" Filter: ((capture_time >= '2012-01-01 00:00:00'::timestamp without time zone) AND (capture_time < '2012-01-02 00:00:00'::timestamp without time zone) AND (category_id = 100))"
" -> Seq Scan on bigtable_d000h2 bigtable (cost=0.00..974.47 rows=1 width=216)"
" Filter: ((capture_time >= '2012-01-01 00:00:00'::timestamp without time zone) AND (capture_time < '2012-01-02 00:00:00'::timestamp without time zone) AND (category_id = 100))"
" -> Seq Scan on bigtable_d000h3 bigtable (cost=0.00..1351.92 rows=1 width=214)"
" Filter: ((capture_time >= '2012-01-01 00:00:00'::timestamp without time zone) AND (capture_time < '2012-01-02 00:00:00'::timestamp without time zone) AND (category_id = 100))"
" -> Seq Scan on bigtable_d000h4 bigtable (cost=0.00..577.04 rows=1 width=217)"
" Filter: ((capture_time >= '2012-01-01 00:00:00'::timestamp without time zone) AND (capture_time < '2012-01-02 00:00:00'::timestamp without time zone) AND (category_id = 100))"
" -> Seq Scan on bigtable_d000h5 bigtable (cost=0.00..360.67 rows=1 width=219)"
" Filter: ((capture_time >= '2012-01-01 00:00:00'::timestamp without time zone) AND (capture_time < '2012-01-02 00:00:00'::timestamp without time zone) AND (category_id = 100))"
" -> Seq Scan on bigtable_d000h6 bigtable (cost=0.00..1778.18 rows=1 width=214)"
" Filter: ((capture_time >= '2012-01-01 00:00:00'::timestamp without time zone) AND (capture_time < '2012-01-02 00:00:00'::timestamp without time zone) AND (category_id = 100))"
" -> Seq Scan on bigtable_d000h7 bigtable (cost=0.00..315.82 rows=1 width=216)"
" Filter: ((capture_time >= '2012-01-01 00:00:00'::timestamp without time zone) AND (capture_time < '2012-01-02 00:00:00'::timestamp without time zone) AND (category_id = 100))"
" -> Seq Scan on bigtable_d000h8 bigtable (cost=0.00..372.06 rows=1 width=219)"
" Filter: ((capture_time >= '2012-01-01 00:00:00'::timestamp without time zone) AND (capture_time < '2012-01-02 00:00:00'::timestamp without time zone) AND (category_id = 100))"
" -> Seq Scan on bigtable_d000h9 bigtable (cost=0.00..1048.16 rows=1 width=215)"
" Filter: ((capture_time >= '2012-01-01 00:00:00'::timestamp without time zone) AND (capture_time < '2012-01-02 00:00:00'::timestamp without time zone) AND (category_id = 100))"
Allerdings, wenn ich die genauen Modulo Kriterien (category_id%10=0
) in der where-Klausel hinzufügen, funktioniert es perfekt
explain select * from bigtable where capture_time >= '2012-01-01' and capture_time < '2012-01-02' and category_id=100 and category_id%10=0;
"Result (cost=0.00..2154.09 rows=11 width=215)"
" -> Append (cost=0.00..2154.09 rows=11 width=215)"
" -> Seq Scan on bigtable (cost=0.00..0.00 rows=1 width=210)"
" Filter: ((capture_time >= '2012-01-01 00:00:00'::timestamp without time zone) AND (capture_time < '2012-01-02 00:00:00'::timestamp without time zone) AND (category_id = 100) AND ((category_id % 10) = 0))"
" -> Seq Scan on bigtable_d000h0 bigtable (cost=0.00..2154.09 rows=10 width=216)"
" Filter: ((capture_time >= '2012-01-01 00:00:00'::timestamp without time zone) AND (capture_time < '2012-01-02 00:00:00'::timestamp without time zone) AND (category_id = 100) AND ((category_id % 10) = 0))"
Gibt es eine Möglichkeit Partition Pruning Arbeit richtig zu machen, ohne die Modulo hinzufügen zu müssen Bedingung in jeder Abfrage?
Welcher Version enthält? Ich denke, es gab einige Verbesserungen im Hinblick auf die Partitionierung in 9.x –
Sie können die Einschränkung ein wenig weniger ausführlich machen: 'CHECK (category_id% 10 = 1 UND date_trunc ('month', capture_time) = '2012-01 -01 ':: date) ' –
@a_horse_with_no_name Ich benutze 9.1 – Dojo