Performance

為什麼 COUNT 查詢比結果集查詢快?

  • February 14, 2019

假設我有兩個相似的查詢,具有復雜的連接;查詢 1 返回行和列:

SELECT col1, col2, col3, ...etc 
FROM MyBigTable
  LEFT JOIN AnotherTable1 On ... etc 
  LEFT JOIN AnotherTable2 On ... etc
WHERE someCol1= val1
AND someCol2= val2
AND etc...

查詢 2 僅返回查詢 1 的行數:

SELECT count(MyBigTable.PKcol)
FROM MyBigTable
  LEFT JOIN AnotherTable1 On ... etc 
  LEFT JOIN AnotherTable2 On ... etc
WHERE someCol1= val1
AND someCol2= val2
AND etc...

不言而喻的邏輯告訴我,SQL 引擎(在大多數數據庫中,比如 SQL Server、MySQL、IBM DB2 等等)將從計數查詢返回的速度比結果集查詢快——至少在我們談論大結果集時. 顯然,通過網路傳輸大量行和列將比僅計算單個標量值花費更長的時間!

我的問題是:

  1. 數據庫引擎是否必須為這兩個查詢做類似的工作/努力?
  2. 如果是這樣,瓶頸(或接收結果的延遲)是否僅僅是由於通過網路傳輸更大的數據?

這取決於表和索引佈局,以及您使用的數據庫引擎,但通常有兩個原因使COUNT範例更快:

**1.需要閱讀的頁面更少。**在找到由於連接和過濾操作的結果而需要返回哪些行之後,查詢可能仍需要讀取數據頁以查找要輸出的額外列的值。

情況並非總是如此:如果表設計和查詢是這樣的,無論如何都要對所有內容進行表掃描,那麼這兩個查詢可能會同樣糟糕地執行。同樣在支持聚集索引的數據庫中,如果查詢計劃器最終只使用聚集鍵,則可能不會再進行讀取。此外,您可能有覆蓋索引,這些索引對查找所有所需的輸出資訊所需的工作量具有類似的影響。

使用來自我們其中一個 DB 的 SQL Server 查詢計劃範例(其他 DB 的行為類似):SELECT JobTitleId FROM Person WHERE JobTitleId = 17產生

計劃僅選擇索引值

表明它只需要查看簡單索引即可找到所需的一切。計劃SELECT JobTitleId, LastName, FirstName FROM Person WHERE JobTitleId = 17顯示額外輸出列所需的額外查找: 計劃顯示需要做一些額外工作才能實際計算行數,但這與必須離開並讀取額外數據頁相比非常小: 您可以看到在每種情況下觸摸的頁數:單列和計數範例都顯示以及帶有額外列輸出的範例。

計劃選擇額外的列
SELECT COUNT(*) FROM Person WHERE JobTitleId = 17

選擇計數計劃
SET STATISTICS IO ON``logical reads 2``logical reads 213

**2. 需要傳輸和處理的數據更少。**這通常不如上述重要,但並非總是適用於大數據和/或慢速連接。一旦引擎找到了需要將其發送到呼叫應用程序的數據(可能通過網路而不是通過本地 IPC 響應),應用程序就需要處理和顯示它。您的COUNT查詢只會產生一個具有一個值的行,因此這會很快,另一個查詢可能會導致大量行被傳輸到應用程序並由應用程序處理。

注意: 我在解釋中使用了比您的範例更簡單的查詢,但是對於具有連接、子查詢和其他額外工作的更複雜查詢,考慮因素是相同的,只是可能乘以正在執行的對象的數量。

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