为啥在 FROM 子句中再添加一个 INNER JOIN 会使我的 SQL 查询如此缓慢?

Posted

技术标签:

【中文标题】为啥在 FROM 子句中再添加一个 INNER JOIN 会使我的 SQL 查询如此缓慢?【英文标题】:Why does adding just one more INNER JOIN to a FROM clause make my SQL query so slow?为什么在 FROM 子句中再添加一个 INNER JOIN 会使我的 SQL 查询如此缓慢? 【发布时间】:2014-02-05 23:13:36 【问题描述】:

我正在开发一个带有名为AcmeView 的视图的MS SQL 2008 数据库。当我编写AcmeView 脚本时,我看到它连接了其他三个视图:View1View2View3。一位同事问我是否可以编写一个视图,将AcmeView 的内容与来自另一个视图的数据相结合:NewView

AcmeView在三秒内返回一个结果集;它的组成视图每个都包含数万行。

NewView 是一个小得多的视图;它每个只返回大约两千行;它会在几分之一秒内返回其结果集。

因此,当我将AcmeView 修改为带有NewView 的INNER JOIN 时,结果视图需要将近20 秒才能返回其结果集,这让我很失望。视图可能有什么问题让它变得如此缓慢?

AcmeView 的 SELECT 语句如下所示:

SELECT *
FROM
    View1
    INNER JOIN View2
        ON View2.foo = View1.foo
    INNER JOIN View3
        ON View3.bar = View2.bar    
    -- Executes in 3 seconds

SELECT *
FROM
    View1
    INNER JOIN View2
        ON View2.foo = View1.foo
    INNER JOIN View3
        ON View3.bar = View2.bar
    INNER JOIN NewView
        ON NewView.qwerty = View1.querty
    -- Executes in 20 seconds; why so long?

在我的 FROM 子句中再添加一个视图 NewView 怎么会减慢查询速度,我该怎么办?再一次,NewView 可以在几分之一秒内被查询到。

【问题讨论】:

这个视图有什么作用?它包含多少行? 你需要看一下查询执行计划,看看是什么问题。 索引视图可能会有所帮助。 【参考方案1】:

一个 JOIN 就产生这么大的不同并不难。

如果连接键的排序方式不同 - 很有可能,因为其中一个“表”是一组连接的结果 - 它将全部重新排序或只是在一个大的嵌套循环中完成。

正如@magnus 所说,如果您同时提取两者的执行计划,您可能会很容易看到添加的内容。 我猜它是一个嵌套循环,对于一个表中的每一行,它会扫描另一个表中的每一行。

如果您对执行计划不熟悉,请查看这篇投票率很高的帖子:How to read an execution plan in SQL Server

【讨论】:

看执行计划让我头疼;该图是巨大的,我以前从未尝试过阅读其中之一。也许@Mihai 关于使用索引视图的建议可能会有所帮助? @DanielAllenLangdon 索引视图很麻烦,因为它们有很多限制。我会尝试索引执行计划中存在问题的表。 听起来你肯定比我了解更多。你能告诉我我应该在执行计划中寻找什么以及找到它后我可能会做什么吗? 你知道你今天在这些表上有什么索引吗? 因为这可能是另一种看待它的方式......如果你没有相关的索引,那显然可以尝试。

以上是关于为啥在 FROM 子句中再添加一个 INNER JOIN 会使我的 SQL 查询如此缓慢?的主要内容,如果未能解决你的问题,请参考以下文章

MySQL内连接(INNER JOIN)

在 MS Query 中使用多个 INNER JOIN 的 FROM 子句中的子查询的语法

在 SQL Server 查询的 WHERE 子句中引用或 INNER JOIN 一个 Pandas 数据帧值 [重复]

在 HIVE 插入查询中,为啥 from 子句在开头?

SQLServer中 join 跟inner join的区别是啥?

为啥“在适用于 UPDATE 或 DELETE 语句的目标表的 FROM 子句中”忽略 NOLOCK?