Sql-Server

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

  • September 3, 2022

我有以下表格

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)

這些選擇中的哪一個會表現得更好?

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

這是兩個 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 時是否存在性能差異?

從我看到的兩個計劃是相同的。

實際上,在這種情況下,您將獲得相同形狀的查詢計劃。情況並非總是如此。

執行 select * order by 與 select column order by 時是否存在性能差異?

是的,即使在您使用相同形狀的查詢計劃的情況下,也存在性能差異(儘管在這種特定情況下可能可以忽略不計)。暫時忘記該ORDER BY子句,讓我們談談SELECT *vs SELECT OneSingleColumn,因為無論如何以下都是正確的:

  1. 選擇比需要更多的列(在這種情況下是 7 個額外的列)SELECT *需要定位更多的數據,將其從磁碟載入到記憶體中,進行處理,然後通過網路傳輸給消費者。在您的架構中,這 7 個額外的列每行最多可以包含大約 0.5 KB 的額外數據。在一個大小合適的表中,比如 1 億行大,這將是一個額外的 50 GB 數據,需要執行所有上述步驟。
  2. 它可以/將導致分配更多資源來為查詢提供服務,以支持其他列的所有上述步驟。這減少了本可用於伺服器上同時執行的其他查詢的資源。
  3. 它可以以多種不同的方式產生不同形狀的計劃。當查詢超過臨界點時,最常見的方法之一是獲取SELECT *查詢版本的掃描操作,而不是有效地尋找版本。或者另一種方式是,當一個查詢計劃使用完全不同的索引,而不是在您只需要.SELECT OneSingleColumn``OneSingleColumn
  4. 計劃的形狀可能會發生變化(如 maple_shaft 指出的)影響性能的一種方式是,即使在最佳情況下,在最合適的索引上進行索引查找以服務於查詢,它也可能不會包含所有欄位,即*。因此,您最終會得到一個額外的鍵查找運算符,這會導致額外的工作來從聚集索引中查找剩餘的欄位。或者在一個不太理想的結果中,您最終會掃描聚集索引以滿足查詢,而不是尋找一個更優化的索引,該索引只包含您感興趣的列SELECT(假設您的索引適當地滿足您的查詢)。當你只SELECT您需要的列,並且有一個涵蓋這些列的索引,然後可以使用最佳索引來為您提供查詢,而無需進行額外的操作/工作,並且您很有可能會獲得查找操作也針對該指數,速度非常快。

SELECT *出於多種原因,它也是一種反模式,不僅與性能有關,還與可讀性和可維護性有關:

  1. 為什麼 SELECT * 被認為是有害的?
  2. “SELECT *” 為什麼它是反模式
  3. 為什麼“從表中選擇 *”被認為是不好的做法

引用自:https://dba.stackexchange.com/questions/316360