Select * Order by 与 Select column 按性能排序

lif*_*ney 5 sql-server optimization query-performance

我有以下表格

Create Table dbo.product
(
productId varchar(100) primary key,
productStatus varchar(100),
productRegion varchar(100),
productCreated  datetime,
productUpdated datetime
)
Go

declare @id int = 1
while @id <= 100
Begin

Insert Into dbo.product values ('product'+cast(@id as varchar(10)),'Active','North',getdate(),getdate())
    set @id = @id + 1
End

set @id = 1
while @id <= 100
Begin

Insert Into dbo.product values ('inprod'+ cast(@id as varchar(10)),'InActive','South',getdate(),getdate())
    set @id = @id + 1
End
Go

Create Table dbo.productRef
(
productRef int Identity(1,1) primary key,
productId varchar(100),
productName varchar(100)
)
Go

Insert Into dbo.productRef (productId)
Select top 20 productId
from dbo. product 
Go

declare @id int = 1
while @id <= 20
Begin
    update dbo.productRef
    set productName = 'productName'+convert(varchar(10),@id)
    where productRef = @id

    set @id = @id + 1
End
Go

Create nonclustered index idx_productRef1 On dbo.productRef(productId)
Run Code Online (Sandbox Code Playgroud)

这些选择中哪一个会表现更好?

select p.*
from dbo.product p
join dbo.productref pr
on p.productid = pr.productid
order by p.productUpdated

select p.productId
from dbo.product p
join dbo.productref pr
on p.productid = pr.productid
order by p.productUpdated
Run Code Online (Sandbox Code Playgroud)

以下是两个 select 语句的查询计划:
select * plan:
https://www.brentozar.com/pastetheplan/?id=SyY21P0Jo
select ProductId plan:
https://www.brentozar.com/pastetheplan/?id=BkK -gwA1i

从我看来,这两个计划是相同的。执行 select * order by 与 select column order by 时是否存在性能差异?

J.D*_*.D. 11

从我看来,这两个计划是相同的。

事实上,在这种情况下,您将获得相同形状的查询计划。情况并非总是如此。

执行 select * order by 与 select column order by 时是否存在性能差异?

是的,即使在您的情况下具有相同形状的查询计划,也存在性能差异(尽管在这种特定情况下可能可以忽略不计)。暂时忘记ORDER BY该子句,让我们只讨论SELECT *vs SELECT OneSingleColumn,因为无论如何,以下内容都是正确的:

  1. 选择比需要更多的列(在本例中为 7 个额外列)SELECT *需要定位更多数据,将其从磁盘加载到内存中,进行处理并通过网络传输给消费者。在您的架构中,这 7 个额外列每行最多可以包含大约半 KB 的额外数据。在一个大小合适的表中,假设有 1 亿行,那么执行上述所有步骤将需要额外 50 GB 的数据。

  2. 它可以/将导致分配更多资源来服务查询,以支持附加列的所有上述步骤。这减少了服务器上同时运行的其他查询可用的资源。

  3. 它可以通过多种不同的方式产生不同形状的计划。当查询超过临界点时,最常见的方法之一是对SELECT *查询的版本进行扫描操作,而不是对版本进行有效的搜索。或者另一种方法是,当一个查询计划使用完全不同的索引时,在您只需要.SELECT OneSingleColumnOneSingleColumn

  4. 影响性能的计划形状可能变化的一种方式(如 maple_shaft 所指出的)是,即使在最好的情况下,在最合适的索引上进行索引查找来服务查询,它也可能不会包含所有字段, IE *。因此,您最终会得到一个额外的键查找运算符,从而导致从聚集索引中查找剩余字段的额外工作。或者,在不太理想的结果中,您最终会扫描聚集索引来满足查询,而不是寻找更优化的索引,该索引仅包含您感兴趣的列SELECT(假设您的索引适当地满足您的疑问)。当您只SELECT需要您需要的列,并且有一个覆盖这些列的索引时,则可以使用最佳索引来为您的查询提供服务,而无需进行额外的操作/工作,并且您很有可能获得也针对该索引进行查找操作,速度相当快。

SELECT *出于多种原因,它也是一种反模式,不仅与性能有关,还与可读性和可维护性有关:

  1. 为什么 SELECT * 被认为是有害的?
  2. “SELECT *”为什么是反模式
  3. 为什么“从表中选择 *”被认为是不好的做法


Vla*_*sak 6

这种情况下的差异可以在 SORT 运算符上看到。行大小 27B 与 139B。有 20 行且大小不同,在这种情况下不是问题。对于更宽的表和更多的行,我们可以讨论 KB 与 MB,甚至 GB 数据,具体取决于数据。

从实际经验来看,从用户的角度来看,存在 KB 与 GB 排序差异以及实际性能差异。