SQL Server不区分大小写的排序规则

时间:2010-11-17 12:53:23

标签: sql-server sql-server-2008 collation

在SQL Server中使用不区分大小写的排序规则(在查询性能方面)有什么好处/缺点?

我有一个当前使用不区分大小写的排序规则的数据库,我真的不喜欢它。我非常希望将其更改为区分大小写。更改整理时我应该注意什么?

5 个答案:

答案 0 :(得分:6)

如果更改数据库上的排序规则,则还必须单独更改每个列上的排序规则 - 它们会保留创建表时有效的排序规则设置。

create database CollTest COLLATE Latin1_General_CI_AI
go
use CollTest
go
create table T1 (
    ID int not null,
    Val1 varchar(50) not null
)
go
select name,collation_name from sys.columns where name='Val1'
go
alter database CollTest COLLATE Latin1_General_CS_AS
go
select name,collation_name from sys.columns where name='Val1'
go

结果:

name collation_name
---- --------------
Val1 Latin1_General_CI_AI

name collation_name
---- --------------
Val1 Latin1_General_CI_AI

答案 1 :(得分:5)

我想说在生产数据库中更改为区分大小写的排序规则的最大缺点是,许多(如果不是大多数)您的查询都会失败,因为它们目前被设计为忽略大小写。

我没有尝试更改现有数据库的排序规则,但我怀疑这样做也可能非常耗时。在过程发生时,您可能必须完全锁定用户。除非你在dev上进行了彻底的测试,否则不要试试这个。

答案 2 :(得分:5)

(我将此作为一个单独的答案添加,因为它与我的第一个完全不同。) 好的,找到了一些实际的文档。这个MS KB article表示在不同的排序规则之间存在性能差异,但不是您认为的位置。区别在于 SQL排序规则(向后兼容,但不能识别unicode)和 Windows排序规则(知道unicode):

  

通常,Windows和SQL排序规则之间的性能差异程度不会很大。仅当工作负载受CPU限制而不受I / O或网络速度限制时才会出现差异,并且大部分CPU负担是由字符串操作的开销或SQL Server中执行的比较引起的。

SQL和Windows排序规则都具有区分大小写和不区分大小写的版本,因此听起来这不是主要问题。

丹的优秀文章“Collation Hell”中的另一个“战壕”中的好故事:

  

我继承了一个混合整理环境,其中一方面有更多的校对。不同的排序规则需要使用变通方法来避免“无法解决排序规则冲突”错误,并且这些变通方法会因非表达式而导致性能下降。处理混合校对是一种真正的痛苦,因此我强烈建议您对单一校对进行标准化,并且只有在仔细考虑之后才会出现偏差。

他总结道:

  

我个人认为在选择合适的校对时甚至不应考虑性能。我生活在整理地狱的原因之一是我的前辈们选择二进制排序规则来为我们的高度事务性OLTP系统提供所有性能。除了领先的通配符表扫描搜索之外,我发现我们的不同排序规则没有可衡量的性能差异。性能的真正关键是查询和索引调整而不是整理。如果性能对您很重要,我建议您在根据性能预期选择排序规则之前,使用实际的应用程序查询执行性能测试。

希望这有帮助。

答案 3 :(得分:2)

我找不到任何可以确认正确构造的查询是否在区分大小写且不区分大小写的数据库上工作得更快(尽管我怀疑差异可以忽略不计),但有些事情很清楚对我来说:

  1. 如果您的业务要求没有要求,那么您需要做很多额外的工作(这是HLGEM和Damien_The_Unbeliever的答案的关键)。
  2. 如果您的业务要求没有要求,那么您可能会遇到很多可能的错误。
  3. 如果需要案例敏感查找,则在不区分大小写的数据库中构建性能较差的查询太容易了:
  4. 如下的查询:

    ... WHERE UPPER(GivenName) = 'PETER'
    

    不会在GivenName上使用索引。你会想到这样的事情:

    ... WHERE GivenName = 'PETER' COLLATE SQL_Latin1_General_CP1_CS_AS
    

    会更好,但确实如此。但为了获得最佳性能,您必须执行以下操作:

    ... WHERE GivenName = 'PETER' COLLATE SQL_Latin1_General_CP1_CS_AS
        AND GivenName LIKE 'PETER'
    

    (详见this article

答案 4 :(得分:1)

如果更改数据库排序规则但不更改服务器排序规则(因此它们不匹配),请注意何时使用临时表。除非在其CREATE语句中另有规定,否则它们将使用服务器的默认排序规则而不是数据库的排序规则,这可能会导致JOIN或其他与DB的列进行比较(假设它们也已更改为DB的排序规则,如Damien_The_Unbeliever所暗示的那样)失败。

相关问题