性能对比:Count(字段)、Count(主键)、Count(1)、Count(*)
本文經(jīng)授權(quán)轉(zhuǎn)載自微信公眾號(hào):猿人谷
最近有幾個(gè)小伙伴留言說(shuō)不清楚Count(字段)、Count(主鍵)、Count(1)、Count(*)的區(qū)別,特此寫(xiě)篇短文說(shuō)明下。
以下討論是基于InnoDB引擎。
至于分析性能差別的時(shí)候,可以記住以下幾個(gè)原則:
server層要什么就給什么;
InnoDB只給必要的值
現(xiàn)在的優(yōu)化器只優(yōu)化了count(*)的語(yǔ)義為“取行數(shù)”,其它“顯而易見(jiàn)”的優(yōu)化并沒(méi)有做。接下來(lái),我們一個(gè)個(gè)來(lái)進(jìn)行分析。
對(duì)于count(主鍵id)來(lái)說(shuō),InnoDB引擎會(huì)遍歷整張表,把每一行的id值都取出來(lái),返回給server層。server層拿到id后,判斷是不可能為空的,就按行累加。
對(duì)于count(1)來(lái)說(shuō),InnoDB引擎遍歷整張表,但不取值。server層對(duì)于返回的每一行,放一個(gè)數(shù)字“1”進(jìn)去,判斷是不可能為空的,按行累加。
單看這兩個(gè)用法的差別的話,你就能對(duì)比出來(lái),count(1)執(zhí)行的要比count(主鍵id)快。因?yàn)閺囊娣祷豬d會(huì)涉及到解析數(shù)據(jù)行,以及拷貝字段值的操作。
對(duì)于count(字段)來(lái)說(shuō):
如果這個(gè)“字段”是定義為not null的話,一行行地從記錄里面讀出這個(gè)字段,判斷不能為null,按行累加;
如果這個(gè)“字段”定義允許為null,那么執(zhí)行的時(shí)候,判斷到有可能是null,還要把值取出來(lái)再判斷一下,不是null才累加。也就是前面的第一條原則,server層要什么字段,InnoDB就返回什么字段。
但是count(*)是例外,并不會(huì)把全部字段取出來(lái),而是專(zhuān)門(mén)做了優(yōu)化,不取值。count(*)肯定不是null,按行累加。
看到這里,你一定會(huì)說(shuō),優(yōu)化器就不能自己判斷一下嗎,主鍵id肯定非空啊,為什么不能按照count(*)來(lái)處理,多么簡(jiǎn)單的優(yōu)化啊。
當(dāng)然,mysql專(zhuān)門(mén)針對(duì)這個(gè)語(yǔ)句進(jìn)行優(yōu)化,也不是不可以。但是這種需要專(zhuān)門(mén)優(yōu)化的情況太多了,而且mysql已經(jīng)優(yōu)化過(guò)count(*)了,直接使用這種用法就可以了。
所以結(jié)論是:按照效率排序的話,count(字段) < count(主鍵id) < count(1) ≈ count(*)。所以建議盡量使用count(*)。
有道無(wú)術(shù),術(shù)可成;有術(shù)無(wú)道,止于術(shù)
歡迎大家關(guān)注Java之道公眾號(hào)
好文章,我在看??
總結(jié)
以上是生活随笔為你收集整理的性能对比:Count(字段)、Count(主键)、Count(1)、Count(*)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 数据库设计漫谈之一
- 下一篇: 一致性哈希的分析与实现