如果在 WHERE 子句中用参数(具有相同值)替换常量,为什么查询会急剧减慢?

2023-11-23

我有一个递归查询,如果WHERE子句包含一个常量,但如果我用具有相同值的参数替换该常量,则会变得非常慢。

查询 #1 - 使用常量

;WITH Hierarchy (Id, ParentId, Data, Depth)
AS
( SELECT Id, ParentId, NULL AS Data, 0 AS Depth
  FROM Test
  UNION ALL
  SELECT h.Id, t.ParentId, COALESCE(h.Data, t.Data), Depth + 1 AS Depth
  FROM Hierarchy h
       INNER JOIN Test t ON t.Id = h.ParentId
)
SELECT *
FROM Hierarchy
WHERE Id = 69

查询 #2 - 带参数

DECLARE @Id INT
SELECT @Id = 69

;WITH Hierarchy (Id, ParentId, Data, Depth)
AS
( SELECT Id, ParentId, NULL AS Data, 0 AS Depth
  FROM Test
  UNION ALL
  SELECT h.Id, t.ParentId, COALESCE(h.Data, t.Data), Depth + 1 AS Depth
  FROM Hierarchy h
       INNER JOIN Test t ON t.Id = h.ParentId
)
SELECT *
FROM Hierarchy
WHERE Id = @Id

如果表有 50,000 行,则带有常量的查询运行 10 毫秒,带有参数的查询运行 30 秒(慢 3,000 倍)。

移动最后一个不是一个选项WHERE子句到递归的锚定义,因为我想使用查询来创建视图(没有最后一个WHERE)。从视图中选择将具有WHERE子句(WHERE Id = @Id) - 由于实体框架,我需要这个,但那是另一个故事了。

任何人都可以建议一种方法来强制查询#2(带有参数)使用与查询#1(带有常量)相同的查询计划吗?

我已经尝试过使用索引,但这没有帮助。

如果有人愿意,我也可以发布表定义和一些示例数据。 我正在使用 SQL 2008 R2。

提前谢谢你的帮助!

执行计划 - 查询 #1 - 具有常量

alt text

执行计划 - 查询 #2 - 带参数

alt text


正如 Martin 在该问题下的评论中所建议的那样,问题在于 SQL Server 没有正确下推 WHERE 子句中的谓词 - 请参阅他的评论中的链接。

我最终创建了一个用户定义的表值函数,并将其与 CROSS APPLY 运算符一起使用来创建视图。

让我们看看解决方案本身。

用户定义的表值函数

CREATE FUNCTION [dbo].[TestFunction] (@Id INT)
RETURNS TABLE 
AS
RETURN 
(
    WITH
    Hierarchy (Id,  ParentId, Data, Depth)
    AS(
    SELECT Id, ParentId, NULL AS Data, 0 AS Depth FROM Test Where Id = @Id
    UNION ALL
    SELECT h.Id, t.ParentId, COALESCE(h.Data, t.Data), Depth + 1 AS Depth
        FROM Hierarchy h
            INNER JOIN Test t ON t.Id = h.ParentId
    )
    SELECT * FROM Hierarchy
)

View

CREATE VIEW [dbo].[TestView]
AS
SELECT t.Id, t.ParentId, f.Data, f.Depth
FROM
    Test AS t
    CROSS APPLY TestFunction(Id) as f

常量查询

SELECT * FROM TestView WHERE Id = 69

带参数查询

DECLARE @Id INT
SELECT @Id = 69
SELECT * FROM TestView WHERE Id = @Id

使用参数的查询的执行速度基本上与使用常量的查询一样快。

谢谢马丁和其他人!

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

如果在 WHERE 子句中用参数(具有相同值)替换常量,为什么查询会急剧减慢? 的相关文章

随机推荐

  • Firebase 存储桶不工作

    我想尝试最新的 Firebase 现在有存储 但收到此错误 无法连接到服务器 请在几分钟后重试 重试 当我进入新控制台 存储 文件 时 我该如何解决这个问题 谢谢 有一个已知的错误 如果您登录多个谷歌帐户 帐户切换将无法正确完成 并且会造成
  • 使用属性名称变量创建对象[重复]

    这个问题在这里已经有答案了 是否可以在对象文字属性中使用变量名来创建对象 Example function createJSON propertyName return propertyName Value var myObject cre
  • 从 Google App Engine 迁移有多困难?

    我正在考虑制作一个 最初 小型 Web 应用程序 它最终会有增长的潜力 综合考虑 Google App Engine 似乎是一个非常有吸引力的选择 比如说 用户群和复杂性不断增长 出于某种或其他原因 我需要将 GAE 抛在后面 移民出去会有
  • git SHA 依赖什么?

    我想知道 git SHA 依赖的所有参数是什么 我猜测除了提交的内容之外 还会有一些其他参数 例如时间戳等 SHA 的构建取决于这些参数 我对它所依赖的所有此类参数感兴趣 我还对所有这些参数都相同或强制相同的情况感兴趣 从而导致两个人所做的
  • Spring Security 警告:AuthorityUtils 类是抽象的?

    自从迁移到 Spring Security 3 2 5 RELEASE 和 Spring 4 1 1 RELEASE 以来 我们在 Eclipse Luna 中收到了 Spring Bean 验证警告 确切的警告是 Class org sp
  • 如何使用 C# 在 Windows 8 中设置默认浏览器?

    在 Windows 8 XP VISTA WIN7 之前 我们都可以轻松地做到这一点 只需对注册表进行少量更改即可完成 对于 Windows 8 这就没那么容易了 我还没弄清楚如何做到 Windows 8 也几乎没有下面提到的需要更改的注册
  • 时间是否介于其他两个时间之间?

    例如 我想要做的是在周三晚上 8 00 到凌晨 2 00 之间更改我的网站徽标 从技术上讲 凌晨 2 00 是星期四早上 那么我如何检查当前时间是否在周三晚上 8 00 到凌晨 2 00 之间 嗯 更简单 current time strt
  • 使用 Alamofire (Swift 2) 从 JSON 填充表格视图单元格

    我有以下代码 import UIKit import Alamofire class CheHappyTableViewController UITableViewController NSURLConnectionDelegate var
  • 在java中,我如何处理CompletableFutures并获得第一个完成的期望结果?

    通常 对于 CompletableFuture 我会在结果可用时调用 thenApply 或其他方法来执行某些操作 但是 我现在遇到的情况是 我想处理结果 直到收到阳性结果 然后忽略所有进一步的结果 如果我只想获取第一个可用结果 我可以使用
  • Spark Dataframes-按键减少

    假设我有一个像这样的数据结构 其中 ts 是某个时间戳 case class Record ts Long id Int value Int 给定大量这些记录 我希望最终得到每个 id 具有最高时间戳的记录 使用 RDD api 我认为以下
  • 构建 WAR 包时 Maven 错误(缺少 web.xml..?)

    执行时mvn install 我收到以下错误 组装 WAR 时出错 webxml 属性 是必需的 或预先存在的 WEB INF web xml 如果在更新中执行 模式 我的Web应用程序结构树是这样的 my app pom xml src
  • Spring AMQP RabbitMq 中的计划/延迟消息传递

    我正在努力寻找 Spring AMQP Rabbit MQ 中计划 延迟消息的方法 经过大量搜索后 我仍然无法在 Spring AMQP 中做到这一点 有人可以告诉我该怎么做吗x delay在 Spring AMQP 中 如果消费者端发生一
  • 有没有办法在 C# 中比较两个列表[关闭]

    Closed 这个问题需要调试细节 目前不接受答案 我通过以下方式比较两个列表 var listOne new List
  • 我应该在 Struts2 视图层中检索数据库记录吗?

    我有一个编辑页面 我想在其中检索subjects and levels从数据库中显示并显示为用户编辑的选择选项course 当表单提交时 它会发出一个新的请求 用户输入被捕获课程Bean带有 XML 验证 当XML验证失败时 它将转发课程B
  • 是否有任何 C# 框架或代码来解析 *blg 性能计数器日志文件?

    任务不是在我的 NET 应用程序中收集性能计数器数据 而是打开已经准备好的二进制日志文件 blg 我知道 MS SQL Profiler NET 应用程序 可以解析二进制日志 据我所知 blg 文件格式似乎是专有的 并且规范并未公开发布 也
  • 为什么我应该关心轻量级标签与带注释的标签?

    去年 我从 Subversion 转向 Git 作为我的日常 VCS 并且仍在努力掌握 Git think 的精髓 最近困扰我的是 轻量级 与带注释和签名的标签 似乎人们普遍认为 在所有实际用途中 带注释的标签都优于轻量级标签 但我找到的解
  • 为 64 位 Windows 10 PC 下载并安装 PyBluez?

    我正在尝试将蓝牙与 python 一起使用 并且遇到了一个模块 pybluez 就在那时 我尝试通过运行 pip install pybluez 来安装它 该包已找到并下载 但在运行 python setup py Egg info 时出现
  • 从文件中提取快速傅立叶变换数据

    我正在构建一个应该在服务器上运行并分析声音文件的工具 我想在 Ruby 中执行此操作 因为我的所有其他工具也是用 Ruby 编写的 但我很难找到实现这一目标的好方法 我发现的很多例子都是在做可视化和图形化的东西 我只需要 FFT 数据 仅此
  • 如何使用 Selenium/PhantomJS 列出加载的资源?

    我想加载一个网页并列出该页面的所有加载资源 javascript images css 我使用此代码来加载页面 from selenium import webdriver driver webdriver PhantomJS driver
  • 如果在 WHERE 子句中用参数(具有相同值)替换常量,为什么查询会急剧减慢?

    我有一个递归查询 如果WHERE子句包含一个常量 但如果我用具有相同值的参数替换该常量 则会变得非常慢 查询 1 使用常量 WITH Hierarchy Id ParentId Data Depth AS SELECT Id ParentI