在COLLATION更改后,SQL Server停止使用INDEX

问题描述 投票:1回答:1

更新:问题被重写,所以一些评论可能不再相关。

在表中更改了排序规则后,我们遇到了索引使用方面的问题。出现了很多扫描。默认数据库排序规则是SQL_Latin1_General_CP1_CI_AS。现在让我们来看看这个例子:

IF OBJECT_ID('colltest') > 0 DROP TABLE CollTest;

CREATE TABLE dbo.CollTest
(
    cs       CHAR(8) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL
  , ci       CHAR(8) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL
  , cs_latin CHAR(8) COLLATE Latin1_General_CS_AS NOT NULL
  , ci_latin CHAR(8) COLLATE Latin1_General_CI_AS NOT NULL
);

CREATE INDEX ix_cs ON dbo.CollTest (cs);

CREATE INDEX ix_ci ON dbo.CollTest (ci);

CREATE INDEX ix_cs_latin ON dbo.CollTest (cs_latin);

CREATE INDEX ix_ci_latin ON dbo.CollTest (ci_latin);

WITH q (n) AS (SELECT 1
               UNION ALL
               SELECT 1
               UNION ALL
               SELECT 1
               UNION ALL
               SELECT 1
               UNION ALL
               SELECT 1
               UNION ALL
               SELECT 1
               UNION ALL
               SELECT 1
               UNION ALL
               SELECT 1
               UNION ALL
               SELECT 1
               UNION ALL
               SELECT 1)
   , q100 (n) AS (SELECT 1 FROM q a, q b)
   , q10000 (n) AS (SELECT 1 FROM q100 a, q100 b)
   , q100000 (n) AS (SELECT 1 FROM q a, q10000 b)
INSERT INTO dbo.CollTest
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) step
     , ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) step
     , ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) step
     , ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) step
  FROM q100000;

以下是以下查询的解释计划:

SELECT cs FROM dbo.colltest WHERE cs = CAST('1000000' AS NVARCHAR(MAX))
SELECT ci FROM dbo.colltest WHERE ci = CAST('1000000' AS NVARCHAR(MAX))
SELECT cs_latin FROM dbo.colltest WHERE cs_latin = CAST('1000000' AS NVARCHAR(MAX))
SELECT ci_latin FROM dbo.colltest WHERE ci_latin = CAST('1000000' AS NVARCHAR(MAX))

enter image description here

所以它表明当COLLATION是SQL_ *然后它使用扫描,当拉丁*然后它使用搜索。这是为什么?

sql-server indexing sql-server-2014 collation query-performance
1个回答
1
投票

这在Comparing SQL collations to Windows collations中有解释

对于Windows排序规则,使用与Unicode数据相同的算法来实现非Unicode数据的比较。 ...在SQL排序规则中,SQL Server为非Unicode数据定义了不同的比较语义。

qazxsw poi的数据类型优先级高于qazxsw poi,所以当你将NVARCHAR列与VARCHAR进行比较时,该列需要隐式转换。

示例数据

VARCHAR

查询

NVARCHAR

能够执行DECLARE @T TABLE ( SQL_CollationVC VARCHAR(1) COLLATE SQL_Latin1_General_CP1_CI_AS, Win_CollationVC VARCHAR(1) COLLATE Latin1_General_CS_AS, INDEX SQL_CollationVC(SQL_CollationVC), INDEX Win_CollationVC(Win_CollationVC) ); INSERT INTO @T VALUES (N'¹',N'¹'), (N'½',N'½'), (N'¾',N'¾'), (N'0',N'0'), (N'1',N'1'); 并调用SELECT Win_CollationVC FROM @T WHERE Win_CollationVC = N'1' 将谓词转换为dynamic seek指数的可搜索索引范围。

GetRangeThroughConvert

对于查询

varchar

你看到一个扫描

enter image description here

请注意,这会返回两个结果SELECT SQL_CollationVC FROM @T WHERE SQL_CollationVC = N'1' <code>enter image description here</code>

还要注意这个结果

¹

此列的索引将按照从上面返回的顺序存储。

1

SELECT SQL_CollationVC FROM @T ORDER BY SQL_CollationVC +-----------------+ | SQL_CollationVC | +-----------------+ | ¹ | | ½ | | ¾ | | 0 | | 1 | +-----------------+ 不会在索引中彼此相邻存储,因此无法将谓词1转换为对该索引的简单搜索。

© www.soinside.com 2019 - 2024. All rights reserved.