首页 > 解决方案 > 在子查询中使用 select * 会产生糟糕的性能吗?

问题描述

我知道select *在主查询中使用不好的原因。但是在子查询中会发生什么?

  1. 是否从表中检索到所有列,然后仅选择外部选择子句中列出的列?

  2. 查询是否已优化,并且仅从表中检索到之后要选择的列?

真实查询示例:

SELECT     T1.clave, 
           T1.titulo, 
           T1.revision, 
           T1.fecharevision, 
           T1.revisadopor, 
           T1. aprobadopor, 
           T1.nombrearchivo, 
           T1.descripcionarchivo, 
           T1.claverelacionada, 
           T1.archivo, 
           T1.link, 
           T1.fecharevlast, 
           T1.estatus 
    FROM   (SELECT *,
                   Row_number() 
                     OVER( 
                       partition BY revision 
                       ORDER BY fecharevlast DESC ) AS orden 
            FROM   motoresemis) AS T1 
    WHERE  T1.clave = 'CMD-01' AND T1.orden = 1

标签: sql-server

解决方案


对于简单的示例,它不会产生影响 - SQL Server 是一种“声明性”语言,这意味着 SQL 命令指示您想要什么,而不是如何去做。

例如,我有一个名为 Test10k 的简单表,它有 10,000 行,ID 为 PK 整数,然后 Col2、Col3、Col4、Col5 为填充有 GUID 的 varchar(100)。Col2 上有一个非聚集索引。

以下命令都使用相同的计划、基数估计和 IO 统计信息执行完全相同的操作

SELECT  ID, rn
FROM    (SELECT ID, ROW_NUMBER() OVER (ORDER BY Col2) AS rn
        FROM Test10k
        WHERE Col2 LIKE 'F%'
        ) A;

SELECT  ID, rn
FROM    (SELECT *, ROW_NUMBER() OVER (ORDER BY Col2) AS rn
        FROM Test10k
        WHERE Col2 LIKE 'F%'
        ) A;

SELECT  ID, rn
FROM    (SELECT ID, Col3, ROW_NUMBER() OVER (ORDER BY Col2) AS rn
        FROM Test10k
        WHERE Col2 LIKE 'F%'
        ) A;
  • 前两个使用所需的特定值与 * 比较子查询。
  • 第三个显式使用不在非聚集索引中的另一列 (Col3);SQL Server 确定不需要它,因此无论如何都从非聚集索引中获取数据。

SELECT * 最大的问题是在复杂的设置中(尤其是分组等),即使在逻辑上可以使用索引,它也可能不使用索引,因为您的命令足够复杂,SQL Server 会按照您所说的那样处理这些部分。

此外,当您在子查询中获取几乎整个表时, SELECT * 或 SELECT table.* 通常会更好,因为它更容易阅读(如上面的示例)。如果无论如何您都在使用几乎所有字段,那么无论如何都需要使用聚集索引来获取数据。

所以,我的建议

  • 尝试使用显式列表,以防万一
  • 但是,当给定表中的列列表变得太长/多于少数列时,可以使用 SELECT * (但请考虑,如果连接表,请使用 SELECT 表。*)

推荐阅读