MySQL實(shí)戰(zhàn)45講 第十四講筆記

count(*)的實(shí)現(xiàn)方式

不同的存儲(chǔ)引擎在實(shí)現(xiàn)count(*)的方式上不同

MyISAM 引擎把一個(gè)表的總行數(shù)存在了磁盤(pán)上,因此執(zhí)行 count(*) 的時(shí)候會(huì)直接返回
這個(gè)數(shù),效率很高;
而 InnoDB 引擎就麻煩了,它執(zhí)行 count(*) 的時(shí)候,需要把數(shù)據(jù)一行一行地從引擎里面
讀出來(lái),然后累積計(jì)數(shù)。
如果加入了where條件,MyISAM也不可能返回那么快。

show table status

使用命令,會(huì)返回TABLE_ROWS,但是這個(gè)數(shù)是基于采樣計(jì)數(shù)的不夠準(zhǔn)確。

區(qū)別引擎和show table status

MyISAM 表雖然 count(*) 很快,但是不支持事務(wù);
show table status 命令雖然返回很快,但是不準(zhǔn)確;
InnoDB 表直接 count(*) 會(huì)遍歷全表,雖然結(jié)果準(zhǔn)確,但會(huì)導(dǎo)致性能問(wèn)題。

如果用緩存系統(tǒng)存儲(chǔ)計(jì)數(shù)

存在丟失更新和數(shù)據(jù)不同步的情況,因?yàn)榫彺婧蛿?shù)據(jù)庫(kù)同時(shí)修改并非原子操作。
把計(jì)數(shù)放在 Redis 里面,不能夠保證計(jì)數(shù)和 MySQL 表里的數(shù)據(jù)精確一致的原因,
是這兩個(gè)不同的存儲(chǔ)構(gòu)成的系統(tǒng),不支持分布式事務(wù),無(wú)法拿到精確一致的視圖。而把計(jì)數(shù)值也放在 MySQL 中,就解決了一致性視圖的問(wèn)題。

數(shù)據(jù)庫(kù)保存計(jì)數(shù)

  • 不會(huì)丟失更新
  • 同時(shí)利用事務(wù)特性,同步計(jì)數(shù)和實(shí)際表內(nèi)容

不同count用法

count語(yǔ)義,聚合函數(shù),對(duì)于返回的結(jié)果集合一行行地進(jìn)行判斷,如果count的值不為空,計(jì)數(shù)加一,最后返回累計(jì)值。
count(*)、count(主鍵 id) 和 count(1) 都表示返回滿(mǎn)足條件的結(jié)果集的總行數(shù);而
count(字段),則表示返回滿(mǎn)足條件的數(shù)據(jù)行里面,參數(shù)“字段”不為 NULL 的總個(gè)數(shù)。

  • count(*),優(yōu)化器優(yōu)化了 count(*) 的語(yǔ)義為“取行數(shù)”
  • count(主鍵 id),InnoDB 引擎會(huì)遍歷整張表,把每一行的 id 值都取出來(lái),返
    回給 server 層。server 層拿到 id 后,判斷是不可能為空的,就按行累加。
  • count(字段)
  1. 如果這個(gè)“字段”是定義為 not null 的話(huà),一行行地從記錄里面讀出這個(gè)字段,判斷不能為 null,按行累加;
  2. 如果這個(gè)“字段”定義允許為 null,那么執(zhí)行的時(shí)候,判斷到有可能是 null,還要把值取出來(lái)再判斷一下,不是 null 才累加
  • count(1) InnoDB 引擎遍歷整張表,但不取值。server 層對(duì)于返回的每一
    行,放一個(gè)數(shù)字“1”進(jìn)去,判斷是不可能為空的,按行累加。

結(jié)論

按照效率排序的話(huà),count(字段)<count(主鍵 id)<count(1)≈count(*),所
以我建議你,盡量使用 count(*)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容