Firebird使用INNER JOIN的非最佳计划

时间:2015-01-14 17:47:16

标签: sql firebird sql-execution-plan

我有一个主表A和一个子表B.A上的每个记录都可以在B中有0..N子记录(就像订单 - >项目关系)。

CREATE TABLE A (
    ID INTEGER NOT NULL,
    ORDER_DATE TIMESTAMP,
    OTHERFIELD CHAR(1),

    CONSTRAINT PK_A PRIMARY KEY (ID)
);
CREATE INDEX IX_A_DATE ON A (ORDER_DATE);

CREATE TABLE B (
    ORDER_ID INTEGER NOT NULL,
    ITEM_NO INTEGER NOT NULL,
    ITEM_VALUE NUMERIC(15,2),

    CONSTRAINT PK_B PRIMARY KEY (ORDER_ID, ITEM_NO),
    CONSTRAINT FK_B_A FOREIGN KEY (ORDER_ID) REFERENCES A (ID) ON UPDATE CASCADE ON DELETE CASCADE
);

然后我在表格中插入了一些随机数据(A中约40k记录和B中约80k记录),导致0.000024的统计PK_A和{{1} 0.000672 }。 OTHERFIELD填充'0'(30k记录)或'1'(10k记录)。

现在,当我运行此查询时:

IX_A_DATE

我得到了这个计划:SELECT a.ID, SUM(b.ITEM_VALUE) FROM A INNER JOIN B ON b.ORDER_ID = a.ID WHERE (a.ORDER_DATE BETWEEN '2014-01-01' AND '2014-12-31') AND (a.OTHERFIELD = '0') GROUP BY a.ID ,运行得非常快。

但是,如果我删除第二个where条件(OTHERFIELD ='0'),服务器会选择此计划:PLAN JOIN (A ORDER PK_A INDEX (IX_A_DATE), B INDEX (FK_B_A)),这是非常不理想和缓慢的。

PS:我正在使用PLAN SORT (JOIN (B NATURAL, A INDEX (PK_A)))因为只应列出非空订单。 INNER JOIN没有问题,我可以过滤非空订单。但LEFT JOIN是首选,因为它可以使用两个表中任意一个的索引来优化查询,具体取决于INNER JOIN条件。

任何人都知道为什么这第二个条件有助于优化选择最佳计划?我认为只有ORDER_DATE条件就足够了,因为这些字段已编入索引。

0 个答案:

没有答案