2010-02-25 5 views
3

J'ai une table partitionnée par deux colonnes, expired et type_id. expired est une partition booléenne et type_id par gamme. Tableau: ExemplesLes contraintes de partition PostgreSQL se comportent étrangement

mos_active_1 
... 
mos_active_15 
mos_expired_1 
... 
mos_expired_15 

Mes contraintes sont définies comme ceci:

ADD CONSTRAINT mos_active_1_check CHECK (expired = false AND type_id < 100) 
... 
ADD CONSTRAINT mos_expired_1_check CHECK (expired = true AND type_id < 100) 

Si je cours maintenant tout comme prévu SELECT * from mos WHERE expired = true AND type_id = 34 fonctionne, juste mos_expired_1 est touché.

Result (cost=0.00..19.77 rows=2 width=627) 
    -> Append (cost=0.00..19.77 rows=2 width=627) 
     -> Seq Scan on mos (cost=0.00..11.50 rows=1 width=627) 
       Filter: (expired AND (type_id = 34)) 
     -> Index Scan using index_mos_expired_1_on_type_id_and_region_id on mos_expired_1 mos (cost=0.00..8.27 rows=1 width=627) 
       Index Cond: (type_id = 34) 
       Filter: expired 

strangly enought SELECT * from mos WHERE expired = false AND type_id = 34 ne fait pas travail. EXPLAIN révèle que mos_expired_1 et mos_active_1 sont interrogés.

Result (cost=0.00..2464.71 rows=5863 width=150) 
    -> Append (cost=0.00..2464.71 rows=5863 width=150) 
     -> Seq Scan on mos (cost=0.00..11.50 rows=1 width=627) 
       Filter: ((NOT expired) AND (type_id = 34)) 
     -> Index Scan using index_mos_expired_1_on_type_id_and_region_id on mos_expired_1 mos (cost=0.00..8.27 rows=1 width=627) 
       Index Cond: (type_id = 34) 
       Filter: (NOT expired) 
     -> Bitmap Heap Scan on mos_active_1 mos (cost=113.68..2444.95 rows=5861 width=150) 
       Recheck Cond: (type_id = 34) 
       Filter: (NOT expired) 
       -> Bitmap Index Scan on index_mos_active_1_on_type_id (cost=0.00..112.22 rows=5861 width=0) 
        Index Cond: (type_id = 34) 

complete SQL (en plus de la création de la table mos réelle)

Je voudrais vraiment savoir si je manque quelque chose ou c'est un problème de planificateur de requêtes.

MISE À JOUR: j'ai pu reproduire le même problème avec un exemple beaucoup plus simple, deux tables ayant une contrainte basées sur expirés:

CREATE TABLE mos (type_id INTEGER UNIQUE, expired boolean); 
CREATE TABLE mos_expired_1 (CHECK (expired = true )) INHERITS (mos); 
CREATE TABLE mos_active_1 (CHECK (expired = false)) INHERITS (mos); 
INSERT INTO mos_expired_1 (type_id,expired) VALUES(1, true); 
INSERT INTO mos_active_1 (type_id,expired) VALUES(2, false); 
EXPLAIN SELECT * from mos where expired = false; 
EXPLAIN SELECT * from mos where expired = true; 
+0

Je peux certainement reproduire, même sur la version la plus récente. Essayez de demander sur la liste de diffusion PostgreSQL, ils sont très très bons. – rfusca

Répondre

1

Il ressemble à l'exclusion de contrainte PostgreSQL sur booléens ne travail. Lorsque vous utilisez integer ou enum alors cela fonctionne bien.

Entier:

CREATE TABLE mos (type_id INTEGER UNIQUE, expired int); 
CREATE TABLE mos_expired_1 (CHECK (expired = 0)) INHERITS (mos); 
CREATE TABLE mos_active_1 (CHECK (expired = 1)) INHERITS (mos); 
INSERT INTO mos_expired_1 (type_id,expired) VALUES(1, 0); 
INSERT INTO mos_active_1 (type_id,expired) VALUES(2, 1); 
analyze; 

EXPLAIN SELECT * from mos where expired = 0; 
           QUERY PLAN         
----------------------------------------------------------------------------- 
Result (cost=0.00..37.76 rows=12 width=8) 
    -> Append (cost=0.00..37.76 rows=12 width=8) 
     -> Seq Scan on mos (cost=0.00..36.75 rows=11 width=8) 
       Filter: (expired = 0) 
     -> Seq Scan on mos_expired_1 mos (cost=0.00..1.01 rows=1 width=8) 
       Filter: (expired = 0) 
(6 rows) 

EXPLAIN SELECT * from mos where expired = 1; 
           QUERY PLAN         
---------------------------------------------------------------------------- 
Result (cost=0.00..37.76 rows=12 width=8) 
    -> Append (cost=0.00..37.76 rows=12 width=8) 
     -> Seq Scan on mos (cost=0.00..36.75 rows=11 width=8) 
       Filter: (expired = 1) 
     -> Seq Scan on mos_active_1 mos (cost=0.00..1.01 rows=1 width=8) 
       Filter: (expired = 1) 
(6 rows) 

Enum:

CREATE TYPE mybool AS ENUM ('true', 'false');          
CREATE TABLE mos (type_id INTEGER UNIQUE, expired mybool); 
CREATE TABLE mos_expired_1 (CHECK (expired = 'true')) INHERITS (mos); 
CREATE TABLE mos_active_1 (CHECK (expired = 'false')) INHERITS (mos); 
INSERT INTO mos_expired_1 (type_id,expired) VALUES(1, 'true'); 
INSERT INTO mos_active_1 (type_id,expired) VALUES(2, 'false'); 
analyze; 

EXPLAIN SELECT * from mos where expired = 'true'; 
           QUERY PLAN         
----------------------------------------------------------------------------- 
Result (cost=0.00..37.76 rows=12 width=8) 
    -> Append (cost=0.00..37.76 rows=12 width=8) 
     -> Seq Scan on mos (cost=0.00..36.75 rows=11 width=8) 
       Filter: (expired = 'true'::mybool) 
     -> Seq Scan on mos_expired_1 mos (cost=0.00..1.01 rows=1 width=8) 
       Filter: (expired = 'true'::mybool) 
(6 rows) 

EXPLAIN SELECT * from mos where expired = 'false'; 
           QUERY PLAN         
---------------------------------------------------------------------------- 
Result (cost=0.00..37.76 rows=12 width=8) 
    -> Append (cost=0.00..37.76 rows=12 width=8) 
     -> Seq Scan on mos (cost=0.00..36.75 rows=11 width=8) 
       Filter: (expired = 'false'::mybool) 
     -> Seq Scan on mos_active_1 mos (cost=0.00..1.01 rows=1 width=8) 
       Filter: (expired = 'false'::mybool) 
(6 rows) 

Je ne sais pas si c'est un bug. Je pense que ce n'est documenté nulle part.

+0

Wow, belle prise je n'ai pas pensé à ça. J'ai posté la même question sur la liste de diffusion postgresql, voyons si c'est vraiment un bug. – dsander

Questions connexes