在SQL Server中使用不区分大小写的排序规则(在查询性能方面)有什么好处/缺点?SQL Server不区分大小写的排序
我有一个数据库,目前正在使用不区分大小写的排序规则,我不太喜欢它。我非常想将其改为区分大小写。更改排序规则时应该注意什么?
在SQL Server中使用不区分大小写的排序规则(在查询性能方面)有什么好处/缺点?SQL Server不区分大小写的排序
我有一个数据库,目前正在使用不区分大小写的排序规则,我不太喜欢它。我非常想将其改为区分大小写。更改排序规则时应该注意什么?
(我说这是一个单独的答案,因为它不是我的第一个显着不同。) 好的,找到一些实际的文档。这MS KB article说,那里有是不同排序之间的性能差异,但不是你认为的地方。所不同的是SQL排序规则之间(向后兼容,但不支持Unicode)和Windows排序(支持Unicode):
一般情况下,在Windows和SQL排序规则之间的性能差异的程度不会重大。仅当工作负载受CPU限制时,才会出现差异,而不受I/O或网络速度的限制,并且此CPU的大部分负担是由字符串操作或在SQL Server中执行的比较造成的。
SQL和Windows排序规则都有区分大小写和不区分大小写的版本,所以它听起来像这不是主要关心的问题。
另一个好故事“从战壕”于丹的优秀文章,题为“Collation Hell”:
我继承了一个混合排序规则环境更加排序规则比我可以指望一方面。不同的排序规则需要解决方法以避免“无法解决排序规则冲突”错误,并且这些解决方法会由于非可搜索表达式而导致性能下降。处理混合归类是一个真正的痛苦,所以我强烈建议你在单个归类中进行标准化,并且只有在仔细预先考虑后才会出现偏差。
他总结道:
我个人不认为性能甚至应该在选择了适当的归类加以考虑。我生活在整理地狱中的原因之一是我的前任选择二进制排序规则来排除我们高度事务性的OLTP系统的每一点性能。除了领先的通配表扫描搜索之外,我发现我们的不同排序规则没有可衡量的性能差异。性能的关键是查询和索引调整,而不是整理。如果性能对您很重要,那么我建议您在根据性能预期选择排序规则之前,先针对实际的应用程序查询执行性能测试。
希望这会有所帮助。
我想说在生产数据库中更改为区分大小写的排序规则的最大缺点是许多(如果不是大多数)查询会失败,因为它们目前设计为忽略大小写。
我还没有尝试更改现有数据库上的排序规则,但我怀疑这样做可能相当耗时。当过程发生时,您可能必须完全锁定用户。除非你已经在dev上进行了彻底的测试,否则不要试试这个。
如果更改数据库的排序规则,则还必须逐个更改它 - 它们维护创建表时生效的排序规则设置。
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。有趣。我不知道。 – 2010-11-17 14:51:58
+1。这是很好的信息。不知道如果更改了DB排序规则,个别列也需要修改。 – 2010-11-17 14:58:54
如果更改数据库的整理,但是不是服务器核对(然后他们不匹配的结果),使用临时表时要小心。除非在他们的CREATE语句中另有规定,否则他们将使用服务器的默认排序规则,而不是数据库的规则排序规则,这可能会导致对数据库列进行JOIN或其他比较(假设他们也更改为DB的排序规则,如Damien_The_Unbeliever所暗示)失败。
我找不到任何证实适当构造询问是否提高工作效率上区分大小写VS不区分大小写的数据库(虽然我怀疑的差异可以忽略不计),但一些事情是清楚的对我说:
喜欢的查询:
... 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的细节)
+1有趣。谢谢(你的)信息。 – 2010-11-17 18:49:50
@BradC:看来你误读了这篇文章。它涵盖了在不区分大小写的列上进行区分大小写搜索的更高效方式,而不是像您似乎已经理解的那样。但是,您确实提出了在区分大小写的列上尝试进行不区分大小写的搜索的可能性的重要问题。我不相信有办法有效地做到这一点(即没有扫描)。这个问题明显强化了你的观点,即如果没有特定的业务需求,不区分大小写的列更好。 – 2011-08-02 15:58:16
@克雷格:哎呀,看起来你是对的。我编辑了我的帖子。 – BradC 2011-08-03 01:13:29
感谢收集这些信息的人。我认为改变排序规则并不值得我这么做。 – 2010-11-17 20:14:44