2

我无法想出正确的关键字来搜索这个问题的答案,所以如果它已经得到回答,我们深表歉意。

考虑以下 SQL 视图:

CREATE VIEW View1 AS
SELECT Column1
      ,Column2
      ,(SELECT SUM(Column3) FROM Table2 WHERE Table2.ID = Table1.ID)  -- Subquery
FROM Table1

如果我运行以下查询,将执行子查询还是 SQL Server 优化查询?

SELECT Column1 FROM View1

我从性能的角度来看这个,比如说,如果视图有很多子查询(如果内部选择引用一个大表,聚合可能需要很长时间)。

我正在使用 SQL Server 2008 R2,但我很想知道 2012 年或 MySQL 的答案是否不同。

谢谢。

4

2 回答 2

4

如前所述,这取决于您的 DBMS(版本和提供者),以确定检查执行计划。这显示了 SQL-Server 2008 的子查询未执行:

在此处输入图像描述

正如您在Column3未选择的顶部计划中看到的那样,该计划只是从 table1 中选择,在包含的底部计划中Column3,查询 table2。

在 SQL-Server 2008 R2中它不被执行。

在 SQL-Server 2012中不执行;

在 MySQL中它被执行,并且两个查询生成相同的计划:

在此处输入图像描述

进一步详细说明,它还取决于您的确切查询以及您的 DBMS。例如:

CREATE VIEW View2
AS
    SELECT  t.ID, t.Column1, t.Column2, t2.Column3
    FROM    Table1 t
            LEFT JOIN
            (   SELECT  ID, Column3 = SUM(Column3)
                FROM    Table2
                GROUP BY ID
            ) t2
                ON t2.ID = t.ID
GO
SELECT  Column1, Column2
FROM    View2;

SELECT  Column1, Column2, Column3
FROM    View2;

在此处输入图像描述

在这种情况下,您会得到与相关子查询相似的结果,如果未选择 column3,则计划仅显示从 table1 中选择,因为LEFT JOIN优化器知道子查询t2与从 table1 中选择无关,并且没有使用列所以它不会打扰它。如果您将 LEFT JOIN 更改为 INNER JOIN,例如

CREATE VIEW View3
AS
    SELECT  t.ID, t.Column1, t.Column2, t2.Column3
    FROM    Table1 t
            INNER JOIN
            (   SELECT  ID, Column3 = SUM(Column3)
                FROM    Table2
                GROUP BY ID
            ) t2
                ON t2.ID = t.ID
GO
SELECT  Column1, Column2
FROM    View3;

SELECT  Column1, Column2, Column3
FROM    View3;

在此处输入图像描述

这两个查询的查询计划表明,由于第二个查询中没有使用聚合列,优化器本质上将视图更改为:

SELECT  t.ID, t.Column1, t.Column2
FROM    Table1 t
        INNER JOIN
        (   SELECT  DISTINCT ID
            FROM    Table2
        ) t2
            ON t2.ID = t.ID;

Distinct Sort从table2的外观和Stream Aggregate.

所以总而言之,这取决于。

于 2013-06-14T11:31:25.793 回答
-1

视图只是一个定义,就像查询中的临时表一样。首先将执行视图后面的查询,然后执行您在视图上的选择。所以是的,子查询将被执行。如果你不想要这个,你应该创建一个没有子查询的新视图。

于 2013-06-14T11:21:23.307 回答