中國(guó)和城鄉(xiāng)建設(shè)部網(wǎng)站首頁(yè)提高百度搜索排名工具
一 . count(*)的實(shí)現(xiàn)方式
-
MyISAM 引擎把一個(gè)表的總行數(shù)存在了磁盤(pán)上,因此執(zhí)行 count() 的時(shí)候會(huì)直接返回這個(gè)數(shù),效率很高;
-
而 InnoDB 引擎就麻煩了,它執(zhí)行 count(*) 的時(shí)候,需要把數(shù)據(jù)一行一行地從引擎里面讀出來(lái),然后累積計(jì)數(shù)。
二. InnoDB為什么不存儲(chǔ)行數(shù)
InnoDB是支持事務(wù)的,默認(rèn)的隔離級(jí)別是可重復(fù)讀。在代碼上就是通過(guò)多版本并發(fā)控制,也就是 MVCC 來(lái)實(shí)現(xiàn)的。每一行記錄都要判斷自己是否對(duì)這個(gè)會(huì)話(huà)可見(jiàn),因此對(duì)于 count(*) 請(qǐng)求來(lái)說(shuō),InnoDB 只好把數(shù)據(jù)一行一行地讀出依次判斷,可見(jiàn)的行才能夠用于計(jì)算“基于這個(gè)查詢(xún)”的表的總行數(shù)。
三.不同count的用法
對(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)去,判斷是不可能為空的,按行累加。
對(duì)于 count(字段) 來(lái)說(shuō):如果這個(gè)“字段”是定義為 not null 的話(huà),一行行地從記錄里面讀出這個(gè)字段,判斷不能為 null,按行累加;如果這個(gè)“字段”定義允許為 null,那么執(zhí)行的時(shí)候,判斷到有可能是 null,還要把值取出來(lái)再判斷一下,不是 null 才累加。
但是count(*)是例外,并不會(huì)把全部字段取出來(lái),而是專(zhuān)門(mén)做了優(yōu)化,不取值。count(*) 肯定不是 null,按行累加。
按照效率排序 count(*) = count(1) > count(主鍵) > count(字段)