SQL Server 2016。
Table1 is (Col11, Col12, Col13)
Table2 is (Col21, Col22, Col23)
Col11和Col21分别是PK,两个索引都是聚类的 Col22引用Col11并编入索引 Col12也被编入索引。
查询:
SELECT count(*)
FROM Table1 t1
JOIN Table2 t2 ON t2.col22 = t1.col11
WHERE t1.col12 = <value>
执行计划使用col12上的索引,但不使用col22上的索引(它使用与Table2不同的索引,在一个甚至不是查询的一部分的列上)。 对于使用散列或嵌套循环连接的两个计划都是如此。
这种行为的潜在原因是什么以及如何解决? 两个表都是〜1亿行,t1.col12的选择率约为2%。
对于那些想要剧本的人:
CREATE TABLE dbo.Table1 (
Col11 BIGINT IDENTITY (1,1),
Col12 BIGINT,
Col13 VARCHAR(100)
)
CREATE TABLE dbo.Table2 (
Col21 BIGINT IDENTITY (1,1),
Col22 BIGINT,
Col23 INTEGER
)
ALTER TABLE dbo.Table1 ADD
CONSTRAINT PK_Table1 PRIMARY KEY (
Col11 ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
ALTER TABLE dbo.Table2 ADD
CONSTRAINT PK_Table2 PRIMARY KEY (
Col21 ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
ALTER TABLE dbo.Table2 WITH NOCHECK ADD
CONSTRAINT FK_Table2_Table1 FOREIGN KEY(Col22)
REFERENCES dbo.Table1 (Col11)
ON DELETE CASCADE
CREATE NONCLUSTERED INDEX IX_Table1_1 ON dbo.Table1 (Col12 ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
CREATE NONCLUSTERED INDEX IX_Table2_1 ON dbo.Table2 (Col22 ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
CREATE NONCLUSTERED INDEX IX_Table2_2 ON dbo.Table2 (Col23 ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)