Почему запрос вешает сервер

serduk
Дата: 01.11.2005 14:58:49
Простенький запрос ставит сервер на колени:
select
    P_ID,
    S_SES,
    P_PRIOR,
    P_VID,
    P_DTBEGIN,
    P_DTEND,
    cast('00:00' as time) + (cast(P_DTEND as time) - cast(P_DTBEGIN as time)) P_DELTAT,
    P_NEW
from PRT
join SES on (P_SES_ID = S_ID)
where
    (P_PRIOR=0 or P_PRIOR=1)
его план:
PLAN JOIN (SES NATURAL,PRT INDEX (PRT_IDX1,PRT_IDX3,PRT_IDX3))
Если убрать одно OR условие, то пашет на ура
select
    P_ID,
    S_SES,
    P_PRIOR,
    P_VID,
    P_DTBEGIN,
    P_DTEND,
    cast('00:00' as time) + (cast(P_DTEND as time) - cast(P_DTBEGIN as time)) P_DELTAT,
    P_NEW
from PRT
join SES on (P_SES_ID = S_ID)
where
    (P_PRIOR=0)
его план:
PLAN JOIN (PRT INDEX (PRT_IDX3),SES INDEX (PK_SES))
Таблицы:
CREATE TABLE SES (
    S_ID          BIGINT NOT NULL,
    S_SES         VARCHAR(18) NOT NULL,
    S_STAND       SMALLINT default 0 NOT NULL
);
ALTER TABLE SES ADD CONSTRAINT PK_SES PRIMARY KEY (S_ID);
CREATE INDEX SES_IDX1 ON SES (S_SES, S_STAND);


CREATE TABLE PRT (
    P_ID        BIGINT NOT NULL,
    P_PRIOR     SMALLINT default 0 NOT NULL,
    P_SES_ID    BIGINT NOT NULL,
    P_VID       CHAR(1) default ' ' NOT NULL,
    P_DTBEGIN   TIMESTAMP,
    P_DTEND     TIMESTAMP,
    P_NEW       SMALLINT default -1 NOT NULL
);
ALTER TABLE PRT ADD CONSTRAINT PK_PRT PRIMARY KEY (P_ID);
CREATE INDEX PRT_IDX1 ON PRT (P_SES_ID);
CREATE INDEX PRT_IDX2 ON PRT (P_DTBEGIN);
CREATE INDEX PRT_IDX3 ON PRT (P_PRIOR);
CREATE INDEX PRT_IDX4 ON PRT (P_NEW);

FB 1.5.2 SS.
Записей в таблице SES 29232
Записей в таблице PRT 1621933
Вопрос: почему с OR условием запрос не фурычит и почему оптимизатор выбрал такой план?
kdv
Дата: 01.11.2005 15:02:23
поищи в предыдущих топиках. этот or уже две недели подряд спрашивают, то один, то другой...
Могун
Дата: 01.11.2005 19:05:21
select
    P_ID,
    S_SES,
    P_PRIOR,
    P_VID,
    P_DTBEGIN,
    P_DTEND,
    cast('00:00' as time) + (cast(P_DTEND as time) - cast(P_DTBEGIN as time)) P_DELTAT,
    P_NEW
from 
  PRT join SES on (P_SES_ID = S_ID)
where
    P_PRIOR between 0 and 1
или
select
    P_ID,
    S_SES,
    P_PRIOR,
    P_VID,
    P_DTBEGIN,
    P_DTEND,
    cast('00:00' as time) + (cast(P_DTEND as time) - cast(P_DTBEGIN as time)) P_DELTAT,
    P_NEW
from 
  PRT join SES on (P_SES_ID = S_ID)
where
    P_PRIOR=0 
union all
select
    P_ID,
    S_SES,
    P_PRIOR,
    P_VID,
    P_DTBEGIN,
    P_DTEND,
    cast('00:00' as time) + (cast(P_DTEND as time) - cast(P_DTBEGIN as time)) P_DELTAT,
    P_NEW
from
  PRT join SES on (P_SES_ID = S_ID)
where
  P_PRIOR=1