Subject | Optimiser not using expected index |
---|---|
Author | |
Post date | 2014-05-30T02:11:23Z |
I have a problem whereby Firebird 2.5.2 (CS / Windows) is not using the expected index. I have confirmed that the index stats are up to date. Here is the reproducible test case:
-- CREATE TABLES
CREATE TABLE TABLE1
(
TABLE1ID INTEGER,
SOMEVALUE INTEGER,
CONSTRAINT PK_TABLE1 PRIMARY KEY (TABLE1ID)
);
CREATE TABLE TABLE2
(
TABLE2ID INTEGER,
TABLE1ID INTEGER,
VALIDFROM DATE,
VALIDTO DATE,
CONSTRAINT PK_TABLE2 PRIMARY KEY (TABLE2ID),
CONSTRAINT FK_TABLE2_TABLE1 FOREIGN KEY (TABLE1ID) REFERENCES TABLE1 ON UPDATE CASCADE ON DELETE CASCADE
);
COMMIT;
-- POPULATE WITH DUMMY DATA
SET TERM ^ ;
EXECUTE BLOCK
AS
DECLARE I INT = 0;
BEGIN
WHILE (I < 50000) DO
BEGIN
INSERT INTO TABLE1 (TABLE1ID, SOMEVALUE) VALUES (:I + 1, 2 * :I);
INSERT INTO TABLE2 (TABLE2ID, TABLE1ID, VALIDFROM, VALIDTO) VALUES ((:I *3) + 1, :I +1, '2000-01-01', CAST('2005-06-30' AS DATE) + :I);
INSERT INTO TABLE2 (TABLE2ID, TABLE1ID, VALIDFROM, VALIDTO) VALUES ((:I *3) + 2, :I +1, CAST('2005-07-01' AS DATE) + :I, CAST('2010-06-30' AS DATE) + :I);
INSERT INTO TABLE2 (TABLE2ID, TABLE1ID, VALIDFROM, VALIDTO) VALUES ((:I *3) + 3, :I +1, CAST('2010-07-01' AS DATE) + :I, '3000-01-01');
I = I + 1;
END
END
^
SET TERM ; ^
COMMIT;
CREATE INDEX IX_TABLE2_EXPECTED ON TABLE2 (TABLE1ID, VALIDFROM, VALIDTO);
COMMIT;
-- SIMPLE QUERY
SELECT *
FROM TABLE2 T
WHERE T.TABLE1ID BETWEEN 1000 AND 1999
AND T.VALIDFROM <= CURRENT_DATE
AND T.VALIDTO >= CURRENT_DATE
The simple query uses the following PLAN causing 3000 indexed reads (according to both monitoring tables and DBWorkbench)
PLAN (T INDEX (FK_TABLE2_TABLE1))
Why would it not use the following plan?
PLAN (T INDEX (IX_TABLE2_EXPECTED))
I would have expected 1000 indexed reads
Even if I force this plan it still performs 3000 reads indicating that it doesn't take advantage of the ValidFrom and ValidTo information in the index.
Am I misunderstanding something?
Thanks in advance
Adam
-- CREATE TABLES
CREATE TABLE TABLE1
(
TABLE1ID INTEGER,
SOMEVALUE INTEGER,
CONSTRAINT PK_TABLE1 PRIMARY KEY (TABLE1ID)
);
CREATE TABLE TABLE2
(
TABLE2ID INTEGER,
TABLE1ID INTEGER,
VALIDFROM DATE,
VALIDTO DATE,
CONSTRAINT PK_TABLE2 PRIMARY KEY (TABLE2ID),
CONSTRAINT FK_TABLE2_TABLE1 FOREIGN KEY (TABLE1ID) REFERENCES TABLE1 ON UPDATE CASCADE ON DELETE CASCADE
);
COMMIT;
-- POPULATE WITH DUMMY DATA
SET TERM ^ ;
EXECUTE BLOCK
AS
DECLARE I INT = 0;
BEGIN
WHILE (I < 50000) DO
BEGIN
INSERT INTO TABLE1 (TABLE1ID, SOMEVALUE) VALUES (:I + 1, 2 * :I);
INSERT INTO TABLE2 (TABLE2ID, TABLE1ID, VALIDFROM, VALIDTO) VALUES ((:I *3) + 1, :I +1, '2000-01-01', CAST('2005-06-30' AS DATE) + :I);
INSERT INTO TABLE2 (TABLE2ID, TABLE1ID, VALIDFROM, VALIDTO) VALUES ((:I *3) + 2, :I +1, CAST('2005-07-01' AS DATE) + :I, CAST('2010-06-30' AS DATE) + :I);
INSERT INTO TABLE2 (TABLE2ID, TABLE1ID, VALIDFROM, VALIDTO) VALUES ((:I *3) + 3, :I +1, CAST('2010-07-01' AS DATE) + :I, '3000-01-01');
I = I + 1;
END
END
^
SET TERM ; ^
COMMIT;
CREATE INDEX IX_TABLE2_EXPECTED ON TABLE2 (TABLE1ID, VALIDFROM, VALIDTO);
COMMIT;
-- SIMPLE QUERY
SELECT *
FROM TABLE2 T
WHERE T.TABLE1ID BETWEEN 1000 AND 1999
AND T.VALIDFROM <= CURRENT_DATE
AND T.VALIDTO >= CURRENT_DATE
The simple query uses the following PLAN causing 3000 indexed reads (according to both monitoring tables and DBWorkbench)
PLAN (T INDEX (FK_TABLE2_TABLE1))
Why would it not use the following plan?
PLAN (T INDEX (IX_TABLE2_EXPECTED))
I would have expected 1000 indexed reads
Even if I force this plan it still performs 3000 reads indicating that it doesn't take advantage of the ValidFrom and ValidTo information in the index.
Am I misunderstanding something?
Thanks in advance
Adam