Postgresql
count(*) 在子查詢中的表現
假設我們有以下查詢:
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 在繼續優化之前會將這兩個查詢重寫為完全相同的內容。這意味著它們兩者之間不會有性能差異。正如預期的那樣,它們具有完全相同的查詢計劃: