kat*_*tit 9 t-sql performance sql-server-2008
我们使用实体框架进行数据库访问,当我们"思考"LIKE语句时 - 它实际上生成了CHARINDEX的东西.所以,这里有两个简单的查询,在我简化它们以证明某个服务器上的一个点之后:
-- Runs about 2 seconds
SELECT * FROM LOCAddress WHERE Address1 LIKE '%1124%'
-- Runs about 16 seconds
SELECT * FROM LOCAddress WHERE ( CAST(CHARINDEX(LOWER(N'1124'), LOWER([Address1])) AS int)) = 1
Run Code Online (Sandbox Code Playgroud)
表现在包含大约100k条记录.地址1是VarChar(100)字段,没什么特别的.
这是两个并排的计划.没有任何意义,显示50%和50%,但执行时间像1:8

我在网上搜索,一般的建议是使用CHARINDEX而不是LIKE.根据我们的经验,情况正好相反.我的问题是导致这个以及如何在没有代码更改的情况下修复它的原因
我将回答我自己的问题,因为很难找到正确的答案,并且SQL Server 2012执行计划输出已指出了该问题。正如您在原始问题中看到的那样-表面上一切看起来都很好。这是SQL Server 2008。
当我在2012年运行相同的查询时,我收到CHARINDEX查询警告。问题是-SQL Server必须执行类型转换。Address1是VarChar,查询的N'1124'是Unicode或NVarChar。如果我这样更改此查询:
SELECT *
FROM LOCAddress
WHERE (CAST(CHARINDEX(LOWER('1124'), LOWER([Address1])) AS int))
Run Code Online (Sandbox Code Playgroud)
然后,它与LIKE查询运行相同。因此,由Entity Framework生成器引起的类型转换导致这种可怕的性能下降。
首先,如您所见,这两个查询是相同的,而且都不能使用索引。CHARINDEX和LIKE对通配符执行相同的操作。例如:%YourValue%。但是,当您使用“ YourValue%”之类的通配符时,性能会有所不同。在这里,LIKE运算符可能会比CHARINDEX更快地执行,因为它可能允许部分扫描索引。现在,就您而言,这两个查询是相同的,但是由于以下可能的原因,性能有所不同:
统计信息:SQL Server维护字符串列中子字符串的统计信息,这些信息由LIKE运算符使用,但不能完全用于CHARINDEX。在这种情况下,LIKE运算符将比CHARINDEX更快地工作。您可以强制SQL Server使用带有适当表提示的CHARINDEX 索引
例如:FROM LOCAddress WITH(INDEX(index_name))
在此处阅读更多内容,在“ 字符串摘要统计信息 ”部分中说:
SQL Server 2008包括获得专利的技术,用于估计LIKE条件的选择性。它为字符列建立子字符串频率分布的统计摘要(字符串摘要)。这包括类型为text,ntext,char,varchar和nvarchar的列。使用字符串摘要,SQL Server可以准确估计LIKE条件的选择性,在该条件下,模式可能具有任意组合的任意数量的通配符。