2016-08-08 9 views
0
SELECT

Wenn in PostgreSQL mit Partitionierung, wo Master dem Tisch Master-Partition istPostgreSQL Einschränkung Ausschluss nicht mit Unterabfrage arbeitet IN

CREATE TABLE master 
(
    _id numeric, 
    name character varying 
); 

und mit zwei Untertabellen

partition_1

CREATE TABLE partition_1 
(
    -- _id numeric, 
    -- name character varying, 
    CONSTRAINT partition_1_check CHECK (_id < 1000) 
)  
INHERITS (master); 
CREATE INDEX partition_1_id_idx 
    ON partition_1 
    USING btree 
    (_id); 

partition_2

CREATE TABLE partition_2 
(
    -- _id numeric, 
    -- name character varying, 
    CONSTRAINT partition_2_check CHECK (_id >= 1000) 
)  
INHERITS (master); 
CREATE INDEX partition_2_id_idx 
    ON partition_2 
    USING btree 
    (_id); 

und eine Tabelle für einige ids (1,3) in diesem Beispiel

CREATE TABLE _ids 
(
_id numeric NOT NULL, 
CONSTRAINT ids_pkey PRIMARY KEY (_id) 
) 

die Anweisung

EXPLAIN SELECT * FROM master WHERE _id IN (SELECT * FROM _ids) 

ergeben eine seq Abtastung beiden Partitionen unabhängig davon, ob _ids enthält Elemente aus partition_1/2 oder nicht.

Hash Semi Join (cost=39.48..141.14 rows=2621 width=14) 
    Hash Cond: (master._id = _ids._id) 
    -> Append (cost=0.00..62.00 rows=4001 width=14) 
     -> Seq Scan on master (cost=0.00..0.00 rows=1 width=14) 
     -> Seq Scan on partition_1 (cost=0.00..30.98 rows=1998 width=13) 
     -> Seq Scan on partition_2 (cost=0.00..31.02 rows=2002 width=15) 
    -> Hash (cost=23.10..23.10 rows=1310 width=32) 
     -> Seq Scan on _ids (cost=0.00..23.10 rows=1310 width=32) 

Wenn ich stattdessen etwas wie

verwenden
SELECT * FROM master WHERE _id IN (1,3) 

ich das gewünschte Ergebnis:

Append (cost=0.00..17.40 rows=5 width=13) 
    -> Seq Scan on master (cost=0.00..0.00 rows=1 width=14) 
     Filter: (_id = ANY ('{1,3}'::numeric[])) 
    -> Bitmap Heap Scan on partition_1 (cost=8.59..17.40 rows=4 width=13) 
     Recheck Cond: (_id = ANY ('{1,3}'::numeric[])) 
     -> Bitmap Index Scan on partition_1_id_idx (cost=0.00..8.58 rows=4 width=0) 
       Index Cond: (_id = ANY ('{1,3}'::numeric[])) 

Wie bekomme ich PostgreSQL richtig Einschränkung Ausschluss zu benutzen?

Hinweis: Ich habe constraint_exclusion Satz

Antwort

2

Dies ist zu lang für einen Kommentar zu partitionieren.

Die Partitionen werden ausgewählt, wenn Postgres diese Abfrage kompiliert. Wenn Sie Konstanten verwenden, weiß die Engine, wo die Daten liegen. Wenn Sie eine Unterabfrage verwenden, weiß Postgres nicht.

Daher verhindert die Verwendung der Unterabfrage, dass die Engine die Partitionen ausnutzt.

+0

AFAIK, das ist völlig in Ordnung als Antwort. Selbst die Dokumentation klärt das nicht mehr auf, abgesehen von dem Hinweis zum Abfrageplaner: * Wenn der Beschränkungsausschluss aktiviert ist, untersucht der Planer die Einschränkungen jeder Partition und versucht zu beweisen, dass die Partition nicht gescannt werden muss, weil sie nicht enthalten kann Alle Zeilen, die die WHERE-Klausel der Abfrage erfüllen. Wenn der Planer dies beweisen kann, schließt er die Partition aus dem Abfrageplan aus. * (Das ist im Grunde das, was Sie geschrieben haben: es kann nichts beweisen, wenn das von anderen Spalten/Unterabfragen/etc. Abhängt). – pozs

+0

Irgendeine Idee, wie man eine bessere Abfrage durchführt, um die Beschränkung zu benutzen? Vielleicht eine Art verschachtelte Abfrage? – baumjamin

Verwandte Themen