我有一个主表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条件就足够了,因为这些字段已编入索引。