MySQL實戰(zhàn) | 14 為什么count(*)越來越慢藏澳?

select count(*) 應(yīng)該是一個比較常用的語句,用來統(tǒng)計記錄行數(shù)耀找。

但是翔悠,慢慢地你會發(fā)現(xiàn),這個語句越來越慢了野芒,為什么呢蓄愁?

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

首先,我們來看下它的實現(xiàn)方式狞悲。

MySQL 中撮抓,不同的存儲引擎,count(*) 的實現(xiàn)方式是不同的摇锋。

1丹拯、MyISAM 引擎,比較簡單粗暴荸恕,直接將表的總行數(shù)存儲在磁盤上乖酬,因此效率很高;

2融求、InnoDB 引擎中咬像,執(zhí)行時,需要一行行的把數(shù)據(jù)查出來,然后累加县昂;

為啥 MyISAM 就可以這樣做呢肮柜?因為它不支持事務(wù)啊,不用擔(dān)心數(shù)據(jù)不一致的問題七芭。

而 InnoDB 就不一樣了素挽。

由于 MVCC 的存在,InnoDB 在當(dāng)前執(zhí)行環(huán)境下狸驳,對一共有多少數(shù)據(jù)行是不確定的预明,比如:

假設(shè),表 t 中有 1000 條數(shù)據(jù)耙箍,有下面三個用戶并行的會話:

1撰糠、A 啟動事務(wù),查詢表的總行數(shù)辩昆;
2阅酪、C 直接插入一條數(shù)據(jù),然后查詢總行數(shù)汁针;
3术辐、B 啟動事務(wù),插入一條數(shù)據(jù)施无,然后查詢總行數(shù)辉词;
4、C 查詢總行數(shù)猾骡;

注意瑞躺,上面啟動的事務(wù)都沒有提交。

image

A兴想、B幢哨、C 查詢的結(jié)果都不相同。

B 讀到的是 1002嫂便,是因為可重復(fù)讀隔離級別的存在捞镰,而 C 未開啟事務(wù),因此無法看到別的事務(wù)的更新毙替;

綜上曼振,InnoDB 引擎中,在每一個會話中蔚龙,都需要逐行讀取數(shù)據(jù),然后計數(shù)返回總行數(shù)映胁。

InnoDB 對 count(*) 的優(yōu)化

InnoDB 中木羹,主鍵索引存儲的是數(shù)據(jù),輔助索引存儲的只是主鍵值。

因此坑填,輔助索引比主鍵索引小得多抛人,輕量得多。

這種情況下脐瑰,InnoDB 在執(zhí)行 count(*) 時妖枚,就會判斷使用哪個索引,會選擇最小的樹來進(jìn)行遍歷苍在。

在保證邏輯正確的前提下绝页,盡量減少掃描的數(shù)據(jù)量,是數(shù)據(jù)庫系統(tǒng)設(shè)計的通用法則之一寂恬。

小結(jié)

1续誉、由于 MyISAM 引擎不需要支持事務(wù),因此可以快速返回 count(*)初肉;
2酷鸦、show table status 命令雖然返回很快,但是不準(zhǔn)確牙咏;
3臼隔、InnoDB 執(zhí)行 count(*) 時會遍歷全表,因此性能較差妄壶;

count(*)摔握、count(1)、count(主鍵)盯拱、count(字段)的區(qū)別

以下盒发,基于 InnoDB。

含義區(qū)別

count() 是一個聚合函數(shù)狡逢,對于返回的結(jié)果集宁舰,會逐行判斷,若返回的不是 NULL奢浑,就會加 1蛮艰,否則不加。

因此雀彼,count(*)壤蚜、count(主鍵 id)count(1) 都表示返回滿足條件的結(jié)果集的總行數(shù);而 count(字段)徊哑,則表示返回滿足條件的數(shù)據(jù)行里面袜刷,參數(shù)“字段”不為 NULL 的總個數(shù)。

性能區(qū)別

分析性能莺丑,考慮以下幾個原則:

1著蟹、server 層要什么就會返回什么墩蔓;
2、InnoDB 只返回必要的值萧豆;
3奸披、優(yōu)化器只優(yōu)化了 count(*)

對于 count(主鍵id),InnoDB 會遍歷全表涮雷,取每行的主鍵 id阵面,返回給 server 層,server 層拿到數(shù)據(jù)后洪鸭,進(jìn)行判斷累加样刷。

對于 count(1),InnoDB 仍遍歷全表卿嘲,但是不取值颂斜,server 層對返回的每一行數(shù)據(jù)新增一個 1,然后進(jìn)行判斷累加拾枣;

因此沃疮,count(1) 要更快些,因為無需取值梅肤。從引擎返回 id 會涉及到解析數(shù)據(jù)行司蔬,以及拷貝字段值的操作。

對于 count(字段)

1姨蝴、如果這個“字段”是定義為 not null 的話俊啼,一行行地從記錄里面讀出這個字段,判斷不能為 null左医,按行累加授帕;2、如果這個“字段”定義允許為 null浮梢,那么執(zhí)行的時候跛十,判斷到有可能是 null,還要把值取出來再判斷一下秕硝,不是 null 才累加芥映。

但是 count(*) 是例外,并不會把全部字段取出來远豺,而是專門做了優(yōu)化奈偏,不取值。count(*) 肯定不是 null躯护,按行累加惊来。

結(jié)論:按照效率排序的話,count(字段)<count(主鍵 id)<count(1)≈count(*)棺滞,所以我建議你唁盏,盡量使用 count(*)内狸。


你的關(guān)注是對我最大的鼓勵!

關(guān)注本公眾號厘擂,后臺回復(fù)「2018」即可獲取傳智播客 2018 最新 Python 和 Java 教程。

公眾號提供CSDN資源免費(fèi)下載服務(wù)锰瘸!


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末刽严,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子避凝,更是在濱河造成了極大的恐慌舞萄,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件管削,死亡現(xiàn)場離奇詭異倒脓,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)含思,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進(jìn)店門崎弃,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人含潘,你說我怎么就攤上這事饲做。” “怎么了遏弱?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵盆均,是天一觀的道長。 經(jīng)常有香客問我漱逸,道長泪姨,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任饰抒,我火速辦了婚禮肮砾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘循集。我一直安慰自己唇敞,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布咒彤。 她就那樣靜靜地躺著疆柔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪镶柱。 梳的紋絲不亂的頭發(fā)上旷档,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天,我揣著相機(jī)與錄音歇拆,去河邊找鬼鞋屈。 笑死范咨,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的厂庇。 我是一名探鬼主播渠啊,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼权旷!你這毒婦竟也來了替蛉?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤拄氯,失蹤者是張志新(化名)和其女友劉穎躲查,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體译柏,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡镣煮,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了鄙麦。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片典唇。...
    茶點(diǎn)故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖黔衡,靈堂內(nèi)的尸體忽然破棺而出蚓聘,到底是詐尸還是另有隱情,我是刑警寧澤盟劫,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布夜牡,位于F島的核電站,受9級特大地震影響侣签,放射性物質(zhì)發(fā)生泄漏塘装。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一影所、第九天 我趴在偏房一處隱蔽的房頂上張望蹦肴。 院中可真熱鬧,春花似錦猴娩、人聲如沸阴幌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽矛双。三九已至,卻和暖如春蟆豫,著一層夾襖步出監(jiān)牢的瞬間议忽,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工十减, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留栈幸,地道東北人愤估。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像速址,于是被迫代替她去往敵國和親玩焰。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 一壳繁、MySQL優(yōu)化 MySQL優(yōu)化從哪些方面入手: (1)存儲層(數(shù)據(jù)) 構(gòu)建良好的數(shù)據(jù)結(jié)構(gòu)震捣。可以大大的提升我們S...
    寵辱不驚丶?xì)q月靜好閱讀 2,415評論 1 8
  • 索引 數(shù)據(jù)庫中的查詢操作非常普遍润樱,索引就是提升查找速度的一種手段 索引的類型 從數(shù)據(jù)結(jié)構(gòu)角度分 1.B+索引:傳統(tǒng)...
    一凡呀閱讀 2,859評論 0 8
  • 轉(zhuǎn) # https://www.cnblogs.com/easypass/archive/2010/12/ 08/...
    呂品?閱讀 9,698評論 0 44
  • count(*) 的實現(xiàn)方式 討論的是沒有過濾條件的 count(*)在不同的 MySQL 引擎中渣触,count(*...
    胖達(dá)_4b7e閱讀 348評論 0 0
  • 細(xì)雨霏霏,黃昏的唐克鎮(zhèn)壹若,寂寥無人嗅钻。 劉叔拉我們到了“九曲”大酒店。酒店大堂和客房部很有些距離店展,冒雨拖了行李养篓,摸索著...
    梅紫cym閱讀 497評論 0 1