Ограничения раздела PostgreSQL ведут себя странно - PullRequest
3 голосов
/ 25 февраля 2010

У меня есть таблица, разделенная на два столбца, expired и type_id. expired - логическое и type_id разбиение по диапазону. Примеры таблиц:

mos_active_1
...
mos_active_15
mos_expired_1
...
mos_expired_15

Мои ограничения настроены так:

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 )

Если я сейчас запускаю SELECT * from mos WHERE expired = true AND type_id = 34, все работает как ожидалось, просто mos_expired_1 ударил.

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

Удивительно достаточно SELECT * from mos WHERE expired = false AND type_id = 34 не не работает. EXPLAIN показывает, что оба mos_expired_1 и mos_active_1 запрашиваются.

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)

полный SQL (помимо фактического создания таблицы mos)

Мне бы очень хотелось узнать, что я что-то упустил или это проблема планировщика запросов.

ОБНОВЛЕНИЕ: Мне удалось воспроизвести ту же проблему на гораздо более простом примере, всего две таблицы с одним ограничением на основе срока действия:

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;

1 Ответ

1 голос
/ 25 февраля 2010

Похоже, что в PostgreSQL ограничение на логические значения не работает. Когда вы используете integer или enum, это работает хорошо.

Integer:

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)

Я не знаю, если это ошибка. Я думаю, что это нигде не задокументировано.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...