使用SQL排序规则影响性能

时间:2011-05-26 22:06:06

标签: sql sql-server linq performance collation

我想查看一些事情:

Q1)Latin1_General_CI_AS是不区分大小写,重音敏感:I.e。 SQL会将以下内容视为相同 - “hello”和“HELLO”

使用LINQ我经常安静:

db.Where(v => v.Email == "some email".ToLower())

Q2)假设我对Q1的理解是正确的,我是否只是浪费处理时间在我的查询中调用ToLower()?

Q3)有人知道使用Latin1_General_bin而不是Latin1_General_CI_AS会有性能提升吗?我已经在博客上进行了性能测试等(想到这个,因为我正在撰写帖子,所以不要看我自己了)

2 个答案:

答案 0 :(得分:4)

通常,SQL比较不区分大小写 但是也有例外,例如在MySQL中,如果使用binary varchar,则比较区分大小写。

所以你的ToLower可能不会完全浪费时间。

Latin1_General_bin区分大小写 而Latin1_General_CI_AS则不然。

在数据库中区分大小写的比较会更快,但如果您想将“某些电子邮件”与“某些电子邮件”匹配,则需要付出代价,您必须将其转换为小写,从而失去所有速度增益。
我没有时间,但我认为这不值得麻烦 我建议在进行微优化之前智能地使用索引和查询。

- 过早的优化是所有邪恶的根源,Donald Knuth。

答案 1 :(得分:3)

真实例子的表现: 表Adres包含320K行数据。我们需要Adres.Id当我们有电子邮件时(如你的例子)。

数据库(和表Adres)排序规则是SQL_Latin1_General_CP1_CI_AS

对于性能优化,在列电子邮件上创建了非聚集索引(包括Adres.Id列)

查询类似:

SELECT  Adres.ID,Email FROM  csc.Adres WHERE EMAIL ='23LMDLh6N@f8CyB7vPL.r4L'

SELECT  Adres.ID,Email FROM  csc.Adres WHERE EMAIL='23LMDLh6N@F8CyB7vPL.r4L' COLLATE Latin1_General_bin

每次查询都返回1行

结果:enter image description here

似乎在第二种情况下,SQL Server没有将查询识别为SARG。为什么?我们来看看细节。 在第一种情况下:

 ScalarOperator ScalarString="CONVERT_IMPLICIT(nvarchar(4000),[@1],0)

第二名:

ScalarOperator ScalarString="CONVERT_IMPLICIT(nvarchar(80),[CSCENTRUMTest].[csc].[Adres].[Email],0)=CONVERT_IMPLICIT(nvarchar(4000),CONVERT(varchar(8000),[@1],0),0)">

因此,在第二种情况下,电子邮件将转换为必需的排序规则。这种情况不是SARG,而是进行了索引扫描。

如果查询无法识别为SARG(例如LIKE '%some email%)',则计划相同。

假设:如果您的查询可以像SARG一样被识别并且您有适当的索引,则首选不进行校对(最好在客户端/服务端进行整理对话)。

您可以在不同的表现调整书/文章中找到SARG信息。