LIKE '%...' 如何在索引上查找?

2024-03-04

我期待这两个SELECT具有相同的执行计划和性能。由于有一个前导通配符LIKE,我期望进行索引扫描。当我运行这个并查看计划时,第一个SELECT行为符合预期(通过扫描)。但第二个SELECT计划显示索引查找,并且运行速度快 20 倍。

Code:

-- Uses index scan, as expected:
SELECT 1
    FROM AccountAction
    WHERE AccountNumber LIKE '%441025586401'

-- Uses index seek somehow, and runs much faster:
declare @empty VARCHAR(30) = ''
SELECT 1
    FROM AccountAction
    WHERE AccountNumber LIKE '%441025586401' + @empty

问题:

当模式以通配符开头时,SQL Server 如何使用索引查找?

奖金问题:

为什么连接空字符串会改变/改进执行计划?

Details:

  • 上有一个非聚集索引Accounts.AccountNumber
  • 还有其他索引,但查找和扫描都打开this index.
  • The Accounts.AccountNumber列可以为空varchar(30)
  • 服务器是SQL Server 2012

表和索引定义:

CREATE TABLE [updatable].[AccountAction](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [AccountNumber] [varchar](30) NULL,
    [Utility] [varchar](9) NOT NULL,
    [SomeData1] [varchar](10) NOT NULL,
    [SomeData2] [varchar](200) NULL,
    [SomeData3] [money] NULL,
    --...
    [Created] [datetime] NULL,
 CONSTRAINT [PK_Account] PRIMARY KEY NONCLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]


CREATE NONCLUSTERED INDEX [IX_updatable_AccountAction_AccountNumber_UtilityCode_ActionTypeCd] ON [updatable].[AccountAction]
(
    [AccountNumber] ASC,
    [Utility] ASC
)
INCLUDE ([SomeData1], [SomeData2], [SomeData3]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]


CREATE CLUSTERED INDEX [CIX_Account] ON [updatable].[AccountAction]
(
    [Created] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

笔记: 这里是actual两个查询的执行计划。对象的名称与上面的代码略有不同,因为我试图使问题保持​​简单。


这些测试(数据库 AdventureWorks 2008R2)显示了会发生什么:

SET NOCOUNT ON;
SET STATISTICS IO ON;

PRINT 'Test #1';
SELECT  p.BusinessEntityID, p.LastName
FROM    Person.Person p
WHERE   p.LastName LIKE '%be%';

PRINT 'Test #2';
DECLARE @Pattern NVARCHAR(50);
SET @Pattern=N'%be%';
SELECT  p.BusinessEntityID, p.LastName
FROM    Person.Person p
WHERE   p.LastName LIKE @Pattern;

SET STATISTICS IO OFF;
SET NOCOUNT OFF;

Results:

Test #1
Table 'Person'. Scan count 1, logical reads 106
Test #2
Table 'Person'. Scan count 1, logical reads 106

The results from SET STATISTICS IO shows that LIO are the same. But the execution plans are quite different: enter image description here

在第一个测试中,SQL Server 使用Index Scan显式但在第二个测试中 SQL Server 使用Index Seek这是一个Index Seek - range scan。在最后一种情况下,SQL Server 使用Compute Scalar运算符来生成这些值

[Expr1005] = Scalar Operator(LikeRangeStart([@Pattern])), 
[Expr1006] = Scalar Operator(LikeRangeEnd([@Pattern])), 
[Expr1007] = Scalar Operator(LikeRangeInfo([@Pattern]))

并且,Index Seek操作员使用Seek Predicate(优化)对于range scan (LastName > LikeRangeStart AND LastName < LikeRangeEnd)加上另一个未优化的Predicate (LastName LIKE @pattern).

LIKE '%...' 如何在索引上查找?

我的回答:这不是“真实的”Index Seek。它是Index Seek - range scan在这种情况下,它具有相同的性能Index Scan.

另请参阅以下之间的区别Index Seek and Index Scan(类似的辩论):那么……是搜索还是扫描? http://sqlblog.com/blogs/paul_white/archive/2011/02/16/so-is-it-a-seek-or-a-scan.aspx.

Edit 1: The execution plan for OPTION(RECOMPILE) (see Aaron's recommendation please) shows, also, an Index Scan (instead of Index Seek): enter image description here

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

LIKE '%...' 如何在索引上查找? 的相关文章

  • 如何优化 postgres 查询

    我正在运行以下查询 SELECT fat FROM Table1 fat LEFT JOIN modo captura mc ON mc id fat modo captura id INNER JOIN loja lj ON lj id
  • MySQL 偏移无限行

    我想构造一个查询 显示表中的所有结果 但从表的开头偏移 5 据我所知 MySQLLIMIT需要一个限制和一个偏移量 有什么办法可以做到这一点吗 来自MySQL LIMIT 手册 http dev mysql com doc refman 5
  • 如何停止 CTE 中的递归?

    我有一个数据库表 如下所示 ID PredecessorID Data 43b1e103 d8c6 40f9 b031 e5d9ef18a739 null 55f6951b 5ed3 46c8 9ad5 64e496cb521a 43b1e
  • RedGate ReadyRoll 的替代品了吗? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找一种经济实惠的 RedGate ReadyRoll 替代方案 以实现 SQL 的持续部署 我
  • Google BigQuery:如何使用 SQL 创建新列

    我想在不使用旧版 SQL 的情况下向现有表添加一列 基本的 SQL 语法是 ALTER TABLE table name ADD column name datatype 我格式化了 Google BigQuery 的查询 ALTER TA
  • android sqlite 如果不存在则创建表

    创建新表时遇到一点问题 当我使用 CREATE TABLE 命令时 我的新表按应有的方式形成 但是当我退出活动时 应用程序崩溃 并且我在 logcat 中得到一个表已存在 如果我使用 CREATE TABLE IF NOT EXISTS 则
  • 使用表达式动态决定打开哪个子报表

    我有一份报告 其中包含几页带有图表 表格等的内容 该报告由总是希望对报告进行小修改的不同客户使用 目前 如果客户想要对第 5 页进行更改 则会通过修改重新创建整个报告 即使唯一的更改是在第 5 页的图表中 更重要的是 一些客户不想看到第 3
  • Sql 查询抛出标识符太长。最大长度为 128

    我正在处理一个简单的更新查询 在执行查询时看到以下错误 我非常清楚 这根本不应该是一个长度问题 可能是什么问题 Error 以identifier开头的标识符太长 最大长度为 128 我的查询 update dbo DataSettings
  • SQL查询:按字符长度排序?

    是否可以按字符总数对sql数据行进行排序 e g SELECT FROM database ORDER BY data length 我想你想用这个 http dev mysql com doc refman 5 0 en string f
  • 删除 DB 但不删除 *.mdf / *.ldf

    我正在尝试自动化分离和删除数据库的过程 通过 VBS objshell run 如果我手动使用 SSMS 分离和删除我可以将数据库文件复制到另一个位置 但是如果我使用 sqlcmd U sa P MyPassword S local Q A
  • 导出 Azure SQL 数据库时出现错误 SQL71501

    导出 Azure SQL 数据库时出现奇怪的错误 导出一直工作正常 直到最近发生一些架构更改 但现在出现错误 SQL71501 该数据库是V12 兼容性级别130 尽管master数据库仍兼容级别 120 该问题似乎是由一个新的表值函数引起
  • 小数除以小数并得到零

    为什么当我这样做时 select CAST 1 AS DECIMAL 38 28 CAST 1625625 AS DECIMAL 38 28 我得到 0 吗 但是当我得到 0 时 select CAST 1 AS DECIMAL 20 10
  • Visual Studio 2008 (C#) 与 SQL Compact Edition 数据库错误:26

    与网络相关或特定于实例的 建立时发生错误 连接到 SQL Server 服务器 未找到或无法访问 验证实例名称是否为 正确并且 SQL Server 是 配置为允许远程 连接 提供商 SQL 网络 接口 错误 26 错误定位 指定服务器 实
  • 如何将数据插入 Microsoft Access 数据库?

    我正在尝试将数据插入 Microsoft Access 数据库 我将数据插入到 Access 数据库中 但只有第一次和第二次显示我插入的数据 当我重建应用程序时 我插入的数据消失了 我不知道他们去了哪里并且没有出现 我使用 C 和 NET
  • 创建用于存储高尔夫球成绩的可扩展数据库架构

    我正在尝试设计一个数据库来存储我所有的朋友和我的高尔夫球成绩 您可能知道 高尔夫得分由 18 洞的个人得分组成 我可以想到两种设计模式的方法 创建一个表 每个洞有一列 例如 h1 到 h18 该表具有引用其他表的 FK player id
  • SQL查询多行变成单行

    有什么方法可以将通常返回具有相同值的多行的 SQL 查询更改为单行吗 例如 如果我现有的查询返回以下内容 ColA ColB 1 AA 1 BB 1 CC 2 AA 3 AA 我可以将查询更改为仅返回 3 行 并将 1 的第二个和第三个结果
  • SQL 解析键值字符串

    我有一个像这样的逗号分隔字符串 key1 value1 key2 value2 key3 value3 key1 value1 1 key2 value2 1 key3 value3 1 我想将它解析成一个如下所示的表 Key1 Key2
  • 使用外部硬盘写入和存储 mysql 数据库

    我已经设置了 mysql 数据库在我的 Mac 上使用 java 和 eclipse 运行 它运行得很好 但现在我将生成大约 43 亿行数据 这将占用大约 64GB 的数据 我存储了大量的密钥和加密值 我有一个 1TB 外部我想用作存储位置
  • OVER ORDER BY 中的多个列

    有没有办法在 OVER ORDER BY 子句中指定多个列 SELECT ROW NUMBER OVER ORDER BY A Col1 AS ID FROM MyTable A 上面的方法工作正常 但尝试添加第二列不起作用 SELECT
  • sql查询连接两个服务器中不同数据库的两个表

    我在 ServerS 上的数据库中有两个表 tableA 在 ServerB 上的数据库中有两个表 我只想根据这些表的公共字段名对这些表执行 fullouter join 在 SQL Server 中 您可以创建一个链接服务器 在 Mana

随机推荐

  • 推荐一款便宜的串口设备

    我需要将我编写的 Java 应用程序与使用串行端口进行通信的医疗设备集成 该设备相当昂贵 而且也不那么便携 我希望能够随时随地测试代码 但在需要插入串行设备并开始测试之前 您只能做这么多 因此 我正在寻找一种使用串行端口进行通信的廉价便携式
  • 从 iframe 中删除滚动条

    使用此代码 这是它的样子 主页上的shoutboxhttp www talkjesus com http www talkjesus
  • Android L 预览版 ActionBar 中的 ProgressBar

    今天 我开始将一个应用程序移植到 Android L 预览版 以便在最终产品发布时使其几乎准备就绪 我发现的一个问题是 ActionBar 上不能有不确定的进度条 它根本不显示并在 logcat 上抛出此错误 E PhoneWindow C
  • IPython:如何将某些内容通过管道传输到 Python 脚本中

    我知道我可以通过以下方式在 IPython 中运行脚本run test py并从那里进行调试 但是如何将输出传输到 test py 中呢 例如 通常我可以在命令行中运行 例如grep ABC input txt test py 但是我如何在
  • 使用 javascript showModalDialog 将值从父表单传递到子表单

    如果我想将我的值传递给确认框 假设我想删除第 1 项 所以当我按下删除按钮时 我选中了复选框 弹出窗口中包含详细信息项目 1 我已经使用显示模式对话框 JavaScript 实现了弹出窗口 但我仍然无法将父值获取到子窗体中 此外 如果我选中
  • 如何获取另一个应用程序当前正在播放的音频[重复]

    这个问题在这里已经有答案了 我如何访问另一个应用程序当前正在播放的音频 实际的音频项目 但也欢迎元数据 我可以看到这个问题已经被问了很多 但多年来提供的解决方案却很少 我理解苹果的理念probably不希望应用程序能够执行此操作 我也明白这
  • Tailwind 自定义颜色在 Next.js 项目中不起作用[重复]

    这个问题在这里已经有答案了 当我分配给变量并使用它时 tailwind config js 中配置的自定义颜色不起作用 如下所示 其中button colour custom blue 颜色数据从cms获取并可以在cms中设置
  • Azure 诊断 - WADLogs 表未创建

    每当用户在云环境中的 WebRole 中执行某些操作时 我都会尝试记录信息 在模拟器中 它将在输出窗口中写入信息 但在 azue 门户中 我在任何地方都看不到信息 我已启用 azure 诊断并提供了 azure 存储凭据 但未创建 azur
  • 如何在Intellij Idea中为Android库项目构建jar而不包含不必要的内容

    当我在 Intellij Idea 中为 Android 库项目构建 jar 时 它会将我在项目中使用的所有依赖 jar 放入其中类 jar 但我认为所有这些东西都是不必要的 jar 只能包含已编译的类 例如 可以编译吗clean想法中的罐
  • 使用 cin >> 和 cout << 填充 C++ 类的字段

    我有一个班在MyClass h定义如下 ifndef MyClass h define MyClass h include
  • 使用 SQL Server 配置 Lucene.Net

    有人使用 Lucene NET 而不是使用 sql server 自带的全文搜索吗 如果是这样 我会对你如何实现它感兴趣 例如 您是否编写了一个每小时查询数据库然后将结果保存到 lucene net 索引的 Windows 服务 是的 我已
  • 为什么 glGetFramebufferAttachmentParameter 不起作用?

    我正在支持 OpenGL3 的设备上尝试以下代码 OpenGL 版本字符串 3 3 0 NVIDIA 310 19 glBindFramebuffer GL FRAMEBUFFER 0 checkGlError glGetFramebuff
  • Azure 函数调用本机 C++

    我正在 Azure 中设计一个新的架构 它是一个多租户 SaaS 应用程序 具有 ASP NET MVC 前端和 blob 存储中的一些应用程序特定数据 我需要在某些时候对此应用程序数据执行一些后台处理 目前这只能使用一些遗留的 C 代码
  • 如果子文档值不存在,Mongodb 插入子文档

    我对 mongodb 很陌生 我有点迷失 我有 mongo 数据库集合 如下所示 id id createdAt new Date name name friends name 1 children name sarah age 12 do
  • html 或 java 脚本代码在硬盘中创建文本文件

    请有人给我一个代码来在硬盘驱动器中创建一个文本文件 结果应该是一个html文件 当双击 html 文件时 它需要在硬盘驱动器 本地 的给定路径中创建一个文本文件 谢谢 出于安全原因 浏览器中常规 HTML 页面中的 JavaScript 不
  • 构造函数中的默认参数--C++

    我有一个 C 类 其中有一个构造函数char char ostream 我想提供一个默认值ostream cerr 这是在标题或 cpp file 您需要将参数设置为参考参数 您不应该尝试复制std cerr 您可能需要在头文件中指定默认参
  • 更改 WPF 中单个/活动窗口的系统语言

    WPF 中是否可以仅更改一个窗口的系统语言 我知道关于InputLanguageManager但我认为它会改变整个系统的语言 InputLanguageManager 完全符合您的要求 它更改当前应用程序的键盘布局 操作系统为每个正在运行的
  • 有没有办法循环遍历 r 中的线性模型的列名称(而不是数字)?

    我有一个包含 40 个数据列 40 种不同的营养素 的数据表 还有用于绘图数字和因子的附加列 我想自动循环每个列名称并为每个列生成一个线性模型和摘要 数据列从第 10 列开始 for i in 10 ncol df for loop ove
  • 将带有 json 的 numpy 数组发送到带有请求的 Flask 应用程序

    使用请求 我需要在单个帖子中将带有 json 数据的 numpy 数组发送到我的 Flask 应用程序 我该怎么做呢 转换 numpy 数组arr到 json 时 可以将其序列化 同时保留维度json dumps arr tolist 然后
  • LIKE '%...' 如何在索引上查找?

    我期待这两个SELECT具有相同的执行计划和性能 由于有一个前导通配符LIKE 我期望进行索引扫描 当我运行这个并查看计划时 第一个SELECT行为符合预期 通过扫描 但第二个SELECT计划显示索引查找 并且运行速度快 20 倍 Code