旧的归类类型会影响数据库性能吗?

Mar*_*sko 5 performance sql-server collation

在我的项目中,我们SQL_1xCompat_CP850_CI_AS用作 SQL Server 实例和应用程序数据库的排序规则设置。据我所知,这是出于向后兼容性目的仍然支持的非常旧的排序规则之一。我想知道使用这种“旧”归类类型是否会影响 SQL Server 的整体性能?

另外,SQL_1xCompat_CP850_CI_ASSQL_Latin1_General_Pref_Cp850_CI_AS整理有什么区别吗?MSDN 上的描述看起来非常相似:在此处输入图片说明 两者都CI_AS_KI_WI使用代码页 850,并且具有相同的排序顺序名称nocase34.850。如果我们将整理设置更改为 ,我们会有什么好处SQL_Latin1_General_Pref_Cp850_CI_AS吗?

Sol*_*zky 9

我想知道使用这种“旧”归类类型是否会影响 SQL Server 的整体性能?

好吧,SQL_1xCompat_CP850_CI_AS和之间不应该有性能差异SQL_Latin1_General_Pref_CP850_CI_AS。两者都是旧的、简单的排序顺序列表,并且不考虑较新的 Windows 排序规则(不以 开头的排序规则SQL_)可以执行的任何 Unicode 语言规则(即使对于VARCHAR数据)。

在典型情况下,使用较新的 Windows 排序规则可能会略微降低性能,因为它们不仅是简单的列表,而且确实利用了 Unicode 语言规则。然而,由于更好的功能,无论性能下降可能是值得的。

性能提升的一个方面是将 NVARCHAR 数据与VARCHAR使用 SQL Server 排序规则(以 开头的排序规则SQL_)进行比较时,需要进行转换。VARCHARNVARCHAR数据相比,使用 Windows 排序规则的索引列不会获得此命中。但这更多是技术说明,而不是大多数查询/场景应该出现的问题。

有什么区别SQL_1xCompat_CP850_CI_ASSQL_Latin1_General_Pref_CP850_CI_AS

如问题中提供的文档所示:是的。它们之间的排序顺序不同。这应该是唯一的区别,因为它们之间的代码页和敏感性是相同的。

请注意,该文档中有两个错误(但这些差异不会改变这两个排序规则之间肯定存在两种不同排序顺序的事实):

  1. 排序顺序 IDSQL_Latin1_General_Pref_CP850_CI_AS是 43,而不是 44
  2. 列出的两个排序规则之间的排序顺序名称不能相同,因为它们是不同的 ID(即使列出的 ID 之一不正确,正确的 ID 仍然不同)。

要查看差异,请尝试以下测试:

设置

CREATE TABLE #CollationTest
(
  [Value] TINYINT NOT NULL PRIMARY KEY,
  [1xCompat] VARCHAR(10) COLLATE SQL_1xCompat_CP850_CI_AS NOT NULL,
  [Latin1] VARCHAR(10) COLLATE SQL_Latin1_General_CP850_CI_AS NOT NULL,
  [Latin1Pref] VARCHAR(10) COLLATE SQL_Latin1_General_Pref_CP850_CI_AS NOT NULL
);

;WITH nums AS
(
  SELECT TOP (256) (ROW_NUMBER() OVER (ORDER BY (SELECT 0)) - 1) AS [num]
  FROM   [master].[sys].[all_columns] ac
)
INSERT INTO #CollationTest ([Value], [1xCompat], [Latin1], [Latin1Pref])
  SELECT [num], CONVERT(VARBINARY(1), [num]), CONVERT(VARBINARY(1), [num]),
         CONVERT(VARBINARY(1), [num])
  FROM nums
  ORDER BY [num] ASC;
Run Code Online (Sandbox Code Playgroud)

测试 1:验证所有字符是否相同

SELECT * FROM #CollationTest;
Run Code Online (Sandbox Code Playgroud)

测试 2:比较它们之间的排序顺序

;WITH compat AS
(
  SELECT ct.[Value], ct.[1xCompat],
         ROW_NUMBER() OVER (ORDER BY ct.[1xCompat] ASC) AS [ord]
  FROM   #CollationTest ct
), lat AS
(
  SELECT ct.[Value], ct.[Latin1],
         ROW_NUMBER() OVER (ORDER BY ct.[Latin1] ASC) AS [ord]
  FROM   #CollationTest ct
), pref AS
(
  SELECT ct.[Value], ct.[Latin1Pref],
         ROW_NUMBER() OVER (ORDER BY ct.[Latin1Pref] ASC) AS [ord]
  FROM   #CollationTest ct
)
SELECT compat.[ord], compat.[1xCompat], lat.[Latin1], pref.[Latin1Pref]
FROM   compat
INNER JOIN lat
        ON lat.ord = compat.ord
INNER JOIN pref
        ON pref.ord = compat.ord
WHERE  compat.[Value] <> lat.[Value]
OR     compat.[Value] <> pref.[Value]
OR     lat.[Value] <> pref.[Value]
ORDER BY compat.[ord] ASC;
Run Code Online (Sandbox Code Playgroud)

差异从第 49 行/值开始,该WHERE子句过滤掉前 48 行,它们都匹配(无聊的东西)。

很明显,排序顺序存在许多差异。其中一个区别是,SQL_1xCompat_CP850_CI_AS52 个非重音字符组合在一起,大写字母始终排在最前面,而重音字符不仅分散在其余字符中,而且大写和小写版本的同一个字母甚至没有放在一起:

m, N, n, O
Run Code Online (Sandbox Code Playgroud)

另一方面,SQL_Latin1_General_Pref_CP850_CI_AS非重音和重音字符都放在一起,按重音分组:

m, N, n, Ñ, ñ, O
Run Code Online (Sandbox Code Playgroud)

如果我们将整理设置更改为 SQL_Latin1_General_Pref_CP850_CI_AS 会有什么好处吗?

很可能唯一真正的好处可能是长寿。我希望微软SQL_1xCompat_CP850_CI_AS在某个时候摆脱。

您应该测试移动到SQL_Latin1_General_Pref_CP850_CI_AS,如果排序顺序的差异不会对应用程序产生不利影响,那么这可能是一个好主意。

转移到 Windows 排序规则可能会更好,但这涉及更多测试,因为还有一些其他功能差异。不幸的是,使用以下我发现没有一个 Windows 排序规则使用代码页 850:

SELECT *
FROM sys.fn_helpcollations()
WHERE  COLLATIONPROPERTY([name], 'CodePage') = 850;
Run Code Online (Sandbox Code Playgroud)

因此,虽然仍然首选使用 Windows 排序规则,但从现有的代码页 850 排序规则更改为更新的排序规则(最有可能使用代码页 1252)是一项更大的测试工作。如果你有时间和资源,我说去吧,否则就做你问的改变:-)。