SQL Server:为啥不区分大小写的列上的 SELECT 比区分大小写的列更快?

Posted

技术标签:

【中文标题】SQL Server:为啥不区分大小写的列上的 SELECT 比区分大小写的列更快?【英文标题】:SQL Server: Why is SELECT on case insensitive column faster than on case sensitive?SQL Server:为什么不区分大小写的列上的 SELECT 比区分大小写的列更快? 【发布时间】:2018-02-19 10:54:50 【问题描述】:

我使用 SQL Server 2016 Express 和带有 JDBC 驱动程序版本 4.2 的 Java 应用程序。

我的数据库的排序规则为Latin1_General_CI_AS(不区分大小写)。我的表有一个VARCHAR(128) NOT NULL 类型的列。该列上有一个唯一索引。

我的测试场景如下:

插入 150000 个 48 个字符长度的字符串后,我随机选择了 200 个现有字符串。我测量所有查询的总执行时间。

然后我删除索引,更改表以将列排序规则更改为Latin1_General_CS_AS(区分大小写)并再次创建唯一索引。

然后 200 次选择总共需要更多时间。

在这两种情况下(CI 和 CS),执行计划都简单且相同(使用索引进行搜索)。

查询执行时间不仅取决于区分大小写。如果字符串具有相同的前缀,则排序规则 CS 会增长得更快。这是我的结果(以秒为单位的执行时间):

+----+---------+------------------+-------------------+-------------------+
|    + RND(48) + CONST(3)+RND(45) + CONST(10)+RND(38) + CONST(20)+RND(28) +
+----+---------+------------------+-------------------+-------------------+
| CI +       6 +                6 +                 7 +                 9 +
| CS +      10 +               20 +                45 +                78 +
+----+---------+------------------+-------------------+-------------------+

随机字符串的相同前缀越长,区分大小写的查询花费的时间就越多。

    为什么在不区分大小写的列上搜索比在区分大小写的列上搜索更快? 相同前缀行为的原因是什么?

【问题讨论】:

search by using the index 是什么意思?索引扫描,而索引查找速度快。发布查询和执行计划 顺便说一句,您在重新创建索引时是否指定了新的排序规则? it grows faster if the strings have identical prefixes 是什么意思?您不能使用索引在字段中间进行搜索,例如使用LIKE %whatever``。只有匹配前缀的查询才能使用索引,即LIKE 'whatever%'任何个查询是否使用索引? 【参考方案1】:

原因是因为您的 SQL 安装(我猜)是使用 CI 排序完成的。这意味着您的 tempdb 和 master 数据库正在使用 CI,目前您自己的数据库也是如此。因此,即使您将字符列更改为 CS,当它在 tempdb 中用于排序/合并操作时,也会在 CI 上下文中执行。要获得准确的比较,您需要将安装排序规则更改为 CS,或者在不同的 SQL 实例上并排进行这些比较 - 一个使用 CS,一个使用 CI。

【讨论】:

除非没有索引或服务器必须存储部分结果的数据太多,否则不会使用 tempdb。如果 使用索引,则可能会发生这种情况。 OP提到的前缀让我想知道查询是否使用LIKE '%something'之类的条件

以上是关于SQL Server:为啥不区分大小写的列上的 SELECT 比区分大小写的列更快?的主要内容,如果未能解决你的问题,请参考以下文章

为啥oracle数据库链接不显示来自sql server的图像类型的列

SQL Server:查询应用在 where 子句中,包含 Json 对象的列上的 IS NOT Null 需要更多时间

DateTime 列上的 Mono InvalidOperationException (SQL Server)

SQL Server 2008 区分大小写的唯一列

sql server数据库区分大小写

只需在 SQL Server 的列上设置 DEFAULT 与设置 CONSTRAINT