sql – LIKE’%…’如何在索引上寻找?
我希望这两个SELECT具有相同的执行计划和性能.由于LIKE上有一个前导通配符,我希望进行索引扫描.当我运行它并查看计划时,第一个SELECT按预期运行(使用扫描).但是第二个SELECT计划显示索引搜索,运行速度提高了20倍.
码: -- Uses index scan,as expected: SELECT 1 FROM AccountAction WHERE AccountNumber LIKE '%441025586401' -- Uses index seek somehow,and runs much faster: declare @empty VARCHAR(30) = '' SELECT 1 FROM AccountAction WHERE AccountNumber LIKE '%441025586401' + @empty 题: 当模式以通配符开头时,SQL Server如何使用索引查找? 奖金问题: 为什么连接空字符串会改变/改进执行计划? 细节: > Accounts.AccountNumber上有一个非聚集索引 表和索引定义: CREATE TABLE [updatable].[AccountAction]( [ID] [int] IDENTITY(1,1) NOT NULL,[AccountNumber] [varchar](30) NULL,[Utility] [varchar](9) NOT NULL,[SomeData1] [varchar](10) NOT NULL,[SomeData2] [varchar](200) NULL,[SomeData3] [money] NULL,--... [Created] [datetime] NULL,CONSTRAINT [PK_Account] PRIMARY KEY NONCLUSTERED ( [ID] ASC )WITH (PAD_INDEX = OFF,STATISTICS_NORECOMPUTE = OFF,IGNORE_DUP_KEY = OFF,ALLOW_ROW_LOCKS = ON,ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] CREATE NONCLUSTERED INDEX [IX_updatable_AccountAction_AccountNumber_UtilityCode_ActionTypeCd] ON [updatable].[AccountAction] ( [AccountNumber] ASC,[Utility] ASC ) INCLUDE ([SomeData1],[SomeData2],[SomeData3]) WITH (PAD_INDEX = OFF,SORT_IN_TEMPDB = OFF,DROP_EXISTING = OFF,ONLINE = OFF,ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] CREATE CLUSTERED INDEX [CIX_Account] ON [updatable].[AccountAction] ( [Created] ASC )WITH (PAD_INDEX = OFF,ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 注意: 解决方法这些测试(数据库AdventureWorks2008R2)显示了发生的情况:SET NOCOUNT ON; SET STATISTICS IO ON; PRINT 'Test #1'; SELECT p.BusinessEntityID,p.LastName FROM Person.Person p WHERE p.LastName LIKE '%be%'; PRINT 'Test #2'; DECLARE @Pattern NVARCHAR(50); SET @Pattern=N'%be%'; SELECT p.BusinessEntityID,p.LastName FROM Person.Person p WHERE p.LastName LIKE @Pattern; SET STATISTICS IO OFF; SET NOCOUNT OFF; 结果: Test #1 Table 'Person'. Scan count 1,logical reads 106 Test #2 Table 'Person'. Scan count 1,logical reads 106 SET STATISTICS IO的结果显示LIO是相同的. 在第一个测试中,SQL Server使用显式索引扫描,但在第二个测试中,SQL Server使用Index Seek,它是一个Index Seek – 范围扫描.在最后一种情况下,SQL Server使用Compute Scalar运算符来生成这些值 [Expr1005] = Scalar Operator(LikeRangeStart([@Pattern])),[Expr1006] = Scalar Operator(LikeRangeEnd([@Pattern])),[Expr1007] = Scalar Operator(LikeRangeInfo([@Pattern])) 并且,Index Seek运算符使用Seek Predicate(优化)进行范围扫描(LastName> LikeRangeStart AND LastName< LikeRangeEnd)加上另一个未优化的Predicate(LastName LIKE @pattern).
我的回答:这不是一个“真正的”索引搜索.这是一个索引搜索范围扫描,在这种情况下,它具有与索引扫描相同的性能. 请参阅Index Seek和Index Scan之间的区别(类似的争论): 编辑1:OPTION(RECOMPILE)的执行计划(请参阅Aaron的推荐)还显示了索引扫描(而不是索引搜索): (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |