Fir*_*xit 2 sql-server t-sql sql-server-2012
这是我第一次处理大型数据库,我想知道为什么下面的两个查询在执行计划方面是不同的。
我在特定表上设置了索引:
CREATE NONCLUSTERED INDEX [IX_UBHSD_xploc_trandt2] ON [dbo].[UBHSD]
(
[xploc] ASC, [trandt2] 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)
ON [PRIMARY]
GO
Run Code Online (Sandbox Code Playgroud)
当我运行此查询时,它使用索引。
SELECT COUNT(*) as cnt
FROM [dbo].[UBHSD]
WHERE [xploc] != '' AND [trandt2] >= CAST('2012-01-01' AS DATETIME)
Run Code Online (Sandbox Code Playgroud)

但是当我在不使用聚合的情况下运行查询时:
SELECT *
FROM [dbo].[UBHSD]
WHERE [xploc] != '' AND [trandt2] >= CAST('2008-01-01' AS DATETIME)
Run Code Online (Sandbox Code Playgroud)

我期望两个查询都使用索引。但是第二个查询执行全表扫描。
为什么会这样?我错过了什么?
您SELECT *可能使用过which 的列数比xplocand 多trandt2。因此 SQL Server 可以通过遍历索引页轻松得出计数。它无法从那里获取不在索引中的其他列,因此它必须转到表中。
根据表中有多少列(以及许多其他因素),在这种情况下,SQL Server 通常可以做出以下两种选择之一:
在您的情况下,该WHERE子句可能满足足够多的行,因此执行扫描实际上更有效。
一些提高效率的方法:
SELECT *- 只需列出您需要的列。INCLUDE所需实际SELECT列表中的其他列。WHERE子句来过滤索引,具体取决于此确切查询是否是频繁运行的查询(以及 2012 年之前是否有大量数据)。顺便说一句,为什么这个表上没有聚集索引?