是的我知道這個問題是類似於這個線程:COUNT(*) vs. COUNT(1) vs. COUNT(pk): which is better?,但這有點不同。有沒有任何性能改善計數(PK)對數(*)
我的前輩說,從count(PrimaryKey)
得到的結果,假設PrimaryKey
不能NULL
,是某種比做正常count(*)
更快。這是真的?
如果這是真的,對所有的RDBMS都是這樣嗎?如果可能的話,請參考(半)官方文件。
是的我知道這個問題是類似於這個線程:COUNT(*) vs. COUNT(1) vs. COUNT(pk): which is better?,但這有點不同。有沒有任何性能改善計數(PK)對數(*)
我的前輩說,從count(PrimaryKey)
得到的結果,假設PrimaryKey
不能NULL
,是某種比做正常count(*)
更快。這是真的?
如果這是真的,對所有的RDBMS都是這樣嗎?如果可能的話,請參考(半)官方文件。
有幾個原因沒關係。首先,兩個符號 - COUNT(1)
和COUNT(*)
- 都是錯誤的語法。考慮關於SUM
聚合的相同問題。哦,SUM(*)
沒有任何意義;爲什麼?因爲,求和是賦值
for(int columnValue : columnList)
currentSum = currentSum + columnValue;
的迭代執行,而對於COUNT
骨料它看起來像這樣
for(Tuple t : tupleList)
currentSum = currentSum + 1;
因此,COUNT
合計不應該有任何參數了!
然後,有各種各樣的語法怪癖,如計數不同。這簡直證明了試圖將兩個連續操作(選擇不同的元組,然後聚合)壓縮到一個操作的SQL設計者的無能。
無關緊要的第二個原因是在實踐中您會遇到無數表現不佳的查詢,並且COUNT(1)
vs COUNT(*)
永遠不是瓶頸。
'COUNT'需要一個可選參數 - 如果給定,它將不會計算行該表達式的計算結果爲'NULL' - 請參閱http://www.postgresql.org/docs/9.2/static/functions-aggregate.html –
因此,您不能先過濾出空值,然後再計數嗎?換句話說,您可以解釋兩次操作的組合,而不是爲每個使用場景引入笨拙的語法。 –
所有SQL聚合函數都會跳過空值:SUM,COUNT,MIN,MAX,AVERAGE等COUNT(*)是奇數。如果你必須先過濾掉,你將無法做到像SELECT COUNT(column_a),COUNT(column_b)FROM table'這樣的東西來計算兩個不同列中的非空值。 –
號這似乎是一個持久的誤解,基於語法之間的混淆
SELECT * FROM ...
和
SELECT COUNT(*) FROM ...
在第一種情況下,*
指所有列,並返回那些肯定需要比返回單個列更多的資源。在第二種情況下,COUNT(*)
只是「計數所有行」的簡寫。錯誤的看法是,COUNT(*)
以某種方式指示數據庫引擎檢查所有行中的所有列,而COUNT(<pk_field>)
只需查看一列。
在這裏有很多關於SO的其他評論引用了SQL-92標準,其中明確指出COUNT(*)
應該只引用表的基數,所以至少在理論上,數據庫引擎應該能夠認識和優化。
據我所知,在這兩種情況下,大多數數據庫引擎(Postgres,Oracle, MySQL InnoDB)只會執行索引掃描來計算行數。如果您指定PK,那麼將使用該索引;如果您只使用COUNT(*)
,那麼查詢計劃器將選擇一個跨越整個表*的索引,但性能應該相同。
我能找到的唯一例外是MySQL和MyISAM表 - 這些表緩存行數,所以COUNT(*)
速度非常快。但是,查詢計劃程序還會將COUNT(<field>)
(其中<field>
是任何非空列)識別爲全表大小的請求,並在該情況下也使用高速緩存。 (source)所以再次,性能沒有差異。
*理論上,如果你沒有這樣的索引,然後COUNT(*)
會很慢,但在這種情況下,COUNT(<pk>)
將是定義
@Ian不可能的:你真的看過我的第一次發言有關的可能性它是相似的? – zfm
我做了,然後在某個地方忘了它 - 對不起,我會盡力讓你的一些研究:) –