Postgresql

count(*) 在子查詢中的表現

  • June 29, 2018

假設我們有以下查詢:

   SELECT COUNT(*) FROM some_big_table WHERE some_col = 'some_val'
   SELECT COUNT(*) FROM ( SELECT * FROM some_big_table WHERE some_col = 'some_val' )

之前的任何查詢是否執行得更好?或者他們是一樣的?

我使用的是 Postgresql 9.4,但是與另一個 DBMS 有很大的不同嗎?

PS:我問這個問題是因為 SQLAlchemy,一個基於 Python 的 ORM,COUNT預設情況下在子查詢上執行操作,但是有一個選項可以強制它COUNT直接在查詢上執行。

你有理由相信他們會有不同的表現嗎?如果是這樣,為什麼不在您的 RDBMS 和您的數據上測試它們呢?一般來說,我會說從最簡單的查詢開始,測試性能,並在必要時只嘗試更複雜的東西(例如選項 2)。

您沒有列出 RDBMS,所以我將給出一個 SQL Server 範例。SQL Server 查詢優化器不直接使用您編寫的 SQL。它將其轉換為內部格式以進行優化。下圖描述了優化的各個階段,並藉用了 Paul White 的Query Optimizer Deep Dive - Part 1

在此處輸入圖像描述

這是我針對公開可用的 Adventure Works 2014 數據庫的測試查詢:

SELECT COUNT(*) 
FROM Sales.SalesOrderDetail 
WHERE CarrierTrackingNUmber = '2E53-4802-85'

在使用未記錄的跟踪標誌 8606 進行簡化後,我可以獲得查詢樹的表示:

*** Simplified Tree: ***
       LogOp_GbAgg OUT(COL: Expr1002 ,)

           LogOp_Select

               LogOp_Get TBL: Sales.SalesOrderDetail Sales.SalesOrderDetail TableID=1154103152 TableReferenceID=0 IsRow: COL: IsBaseRow1000 

               ScaOp_Comp x_cmpEq

                   ScaOp_Identifier QCOL: [AdventureWorks2014].[Sales].[SalesOrderDetail].CarrierTrackingNumber

                   ScaOp_Const TI(nvarchar collate 872468488,Var,Trim,ML=24) XVAR(nvarchar,Owned,Value=Len,Data = (24,506953514552564850455653))

           AncOp_PrjList 

               AncOp_PrjEl COL: Expr1002 

                   ScaOp_AggFunc stopCount

                       ScaOp_Const TI(int,ML=4) XVAR(int,Not Owned,Value=0)

以上是您的查詢計劃的內部表示。該查詢計劃中的實際步驟在這裡並不重要。重要的是我得到了與此查詢完全相同的簡化樹:

SELECT COUNT(*) 
FROM 
(
   SELECT * 
   FROM Sales.SalesOrderDetail 
   WHERE CarrierTrackingNUmber = '2E53-4802-85'
) t;

實際上,這意味著 SQL Server 在繼續優化之前會將這兩個查詢重寫為完全相同的內容。這意味著它們兩者之間不會有性能差異。正如預期的那樣,它們具有完全相同的查詢計劃:

查詢計劃

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