sql - 为什么我的参数化查询不能正确使用索引?
问题描述
这是在 SQL Server 2014 中,但我在 2008、2012 和 2016 以及 Sybase ASE 15.7 中看到了相同的行为。
我有一个简单的查询,如下所示:
SELECT myField
FROM myTable
WHERE someIndexedField = @myParam
如果我从 SSMS 运行此查询(将 @myParam 替换为 'myValue'),查询会在一秒钟内运行,因为 someIndexedField 已编入索引,并且查找速度应该非常快。但是,如果我在 C# 程序中创建与参数化查询字符串相同的查询,则查询需要 20 到 30 秒。DBA 的分析表明查询计划没有使用 someIndexedField 列上的索引,而是执行表扫描。
更奇怪的是,如果我执行完全相同的参数化查询,而是将其稍微更改为:
DECLARE @_myParam char(13)
SET @_myParam = @myParam
SELECT myField
FROM myTable
WHERE someIndexedField = @_myParam
...这个版本突然再次使用索引,性能恢复到亚秒级响应时间。我在各种复杂的查询中看到了同样的行为,但对于不同的查询并不是 100% 一致——有时服务器确实决定使用索引。但是,对于任何给定的查询,它都是一致的。在尝试之前,我永远不知道哪些查询会受到影响,但如果给定的查询有这个问题,它总是有问题。此外,没有问题的查询似乎永远不会在以后开发它。
我注意到的另一件奇怪的事情是,有时,更改查询的总长度实际上会改变这种行为的显示方式。我有一个例子,在查询中添加额外的回车符(基本上是双倍行距)实际上导致服务器突然开始按预期使用索引。从字面上看,没有代码被改变。但是,我无法确定发生这种情况的确切长度。此外,这个特殊的“解决方案”似乎只适用于 Sybase ASE——我无法在 SQL Server 上重现该解决方案。
(顺便提一下,我也可以通过hint来推送服务器使用合适的索引,这样也解决了问题。不过,索引提示如果能避免的话一般不是个好主意,看来服务器应该是完全能够自行选择索引,尤其是对于这样一个简单的查询。)
这里发生了什么?为什么第一个版本运行起来好像表上没有索引?为什么简单地将参数放入本地定义的变量中会突然导致使用索引?
解决方案
推荐阅读
- html - 链接为图像不起作用,但适用于文本
- tfs - 尝试在 Visual Studio 2017 中查看源代码管理资源管理器时出现“找不到网络路径”
- c# - 当用户在带有 AcceptsReturn = "True" 的 UWP 文本框中按下 CTRL+ENTER 键时如何避免换行
- c - 我不明白为什么在这个程序中 a 等于 1 而 b 等于 0
- android - 设备所有者“Kiosk”应用程序在 BOOT_COMPLETED 之前启动,锁定任务替换用户锁定屏幕以获取 PIN 密码
- javascript - 将 CVC 和邮政编码检查传递给 createPaymentMethod stripe.js
- reactjs - 将错误记录到控制台
- java - 全局变量和注入变量之间的区别?
- git - 如何删除整个 git 分支和历史记录
- linux - 使用 sed 在文件的特定行中插入文本。文本包含变量,应在双引号中添加到文件中