如何证明在 SQL 中使用子选择查询会降低服务器的性能
Posted
技术标签:
【中文标题】如何证明在 SQL 中使用子选择查询会降低服务器的性能【英文标题】:How to Prove that using subselect queries in SQL is killing performance of server 【发布时间】:2010-12-28 12:28:33 【问题描述】:我的工作之一是维护我们的数据库,通常我们在获取报告并在该基础上工作时会遇到性能不足的问题。 当我开始查看我们的 ERP 发送到数据库的查询时,我在主查询中看到了很多完全不必要的子选择查询。 由于我不是我们使用的程序的创建者开发人员的成员,所以当我批评他们的代码和工作时,他们不太喜欢。假设他们不将我的评论视为严肃的陈述。 所以我问你几个关于 SQL 中的 subselect 的问题
子选择是否比左外连接花费更多时间? 是否存在任何博客、文章或我选择不建议使用的任何内容? 我如何证明如果我们在查询中避免 subselect 查询会更快?
我们的数据库服务器是MSSQL2005
【问题讨论】:
【参考方案1】:“Show, Don't Tell” - 检查并比较使用 SQL Profiler 识别的查询的查询计划。特别注意表扫描和书签查找(您希望尽可能频繁地查看索引搜索)。查询计划的“拟合优度”取决于最新的统计数据、定义的索引以及整体查询工作负载。
Execution Plan Basics
Understanding More Complex Query Plans
Using SQL Server Profiler(2005版)
在 SQL Server Management Studio (SSMS) 中运行查询并打开 Query->Include Actual Execution Plan (CTRL+M)
认为自己很幸运,它们只是子选择(在某些情况下,优化器会产生等效的“加入计划”)而不是相关的子查询!
确定执行大量逻辑读取的查询,使用您喜欢的技术重写它,然后通过比较显示它执行的逻辑读取次数。
这里有一个提示。要获得执行的逻辑读取的总数,请将相关查询包装为:
SET STATISTICS IO ON
GO
-- Run your query here
SET STATISTICS IO OFF
GO
运行查询,然后切换到结果窗格中的消息选项卡。
如果您有兴趣了解更多信息,没有比 SQL Server 2008 Query Performance Tuning Distilled 更好的书了,它涵盖了监控、解释和修复性能问题的基本技术。
【讨论】:
【参考方案2】:您可以做的一件事是加载 SQL Profiler 并向他们显示子查询的成本(在 CPU 周期、读取和写入方面)。很难与冷酷的统计数据争论。
我还会检查这些查询的查询计划,以确保使用了适当的索引,并将表/索引扫描保持在最低限度。
一般来说,如果使用正确并且有适当的索引,我不会说子查询不好。
【讨论】:
【参考方案3】:我对 MSSQL 不是很熟悉,因为我们在大多数应用程序中都使用 postrgesql。但是应该存在类似“EXPLAIN”的东西,它向您显示查询的执行计划。在那里,您应该能够看到查询为检索所需数据而将产生的各个步骤。
如果您看到有很多表扫描或循环连接没有使用任何索引,这绝对是查询执行缓慢的提示。使用这样的工具,您应该能够比较两个查询(一个有连接,另一个没有)
很难说哪种方法更好,因为它实际上高度依赖于优化器在各种情况下可以采用的索引,并且根据 DBMS,优化器可能能够隐式地将子查询重写为连接-查询并执行。
如果你真的想展示哪个更好,你必须同时执行并测量时间、cpu 使用率等。
更新: MSSQL大概就是这个吧-->QueryPlan
【讨论】:
【参考方案4】:根据我自己的经验,这两种方法都是有效的,例如 EXISTS 子选择可以避免大量处理过早的中断。
但大多数时候,带有大量子选择的查询是由开发人员完成的,他们并不真正了解 SQL,而是使用他们经典的过程程序员的查询思维方式。然后他们甚至不考虑连接,并提出一些糟糕的查询。所以我更喜欢连接,而且我总是检查子查询。老实说,我跟踪慢查询,我第一次尝试包含子选择的慢查询是尝试进行连接。工作很多时间。
但是没有规则可以确定子选择比连接不好或慢,只是糟糕的 sql 程序员经常做子选择:-)
【讨论】:
【参考方案5】:子选择是否比左外连接花费更多时间?
这取决于子选择和左外连接。
一般来说,这个结构:
SELECT *
FROM mytable
WHERE mycol NOT IN
(
SELECT othercol
FROM othertable
)
比这更有效率:
SELECT m.*
FROM mytable m
LEFT JOIN
othertable o
ON o.othercol = m.mycol
WHERE o.othercol IS NULL
看这里:
NOT IN vs. NOT EXISTS vs. LEFT JOIN / IS NULL: SQL Server是否存在建议不要使用 subselect 的任何博客、文章或任何内容?
我会避开那些盲目推荐避免子选择的博客。
它们的实现是有原因的,不管你信不信,开发人员已经付出了一些努力来优化它们。
我如何证明如果我们在查询中避免子选择,查询会更快?
编写一个不带子选择的查询,运行速度更快。
如果您在此处发布您的查询,我们可能会改进它。但是,带有子选择的版本可能会更快。
【讨论】:
【参考方案6】:尝试重写一些查询以消除子选择和比较运行时。
分享和享受。
【讨论】:
以上是关于如何证明在 SQL 中使用子选择查询会降低服务器的性能的主要内容,如果未能解决你的问题,请参考以下文章
当不使用 EXISTS 引入子查询时,选择列表中只能指定一个表达式。 - SQL 服务器