請教一下大家,關於 MySQL 百萬數據量的 count(*) 查詢如何優化?
01-13
-------------8月19日更正 加粗部分----------------
1.sql語句本身優化使用select count(1)或者select count(主鍵)這樣的方式這個優化對於mysql不成立,感謝評論中兩位指正select count(1)和select count(*)是等價的,但是count(col)不同,即使col是主鍵
以下查詢數據全部取自內存中,innodb enginemysql&> select count(id) from sbtest1 where c ="xxxxxxx";+-----------+| count(id) |+-----------+| 0 |+-----------+1 row in set (10.33 sec)用主鍵的查詢用時會更長,如果這裡的col是一個允許為NULL的值,查詢時間會更長+----------+
| count(*) |+----------+| 0 |+----------+1 row in set (9.84 sec)另外從explain extended的結果來看,雖然執行計劃相同,但是count(1) 和count(*)會被優化成count(const值),count(col)不會,這裡應該有什麼額外的判斷,比如判斷了col的NULL問題,具體的差別要翻代碼了(&>~&<)2.sql分拆select count(1) from table where id&>xxx and id &< xxxxx;累加
3.調整策略引入統計的概念,放棄精確值比如explain select count(1) from......這個結果當中有一個列叫做row,表示查詢掃描的行數,如果是根據索引範圍掃的話就是約等於返回的結果級行數,這個值是一個近似的統計值,這個方法用於分頁優化超贊每種資料庫(mysql、oracle等)都會有數據來描述表的信息,包括表的名字、表的大小等信息,這些信息被稱為元數據,所以應該先想到的是mysql是如何存儲表的元數據的,Google一下你就知道答案,mysql有個庫叫information_shcema,這個庫裡面有個表叫TABLES,這個表有個欄位TABLE_ROWS,所以
select TABLE_ROWS from information_schema.`TABLES` WHERE TABLE_NAME = "xxxx"
能粗略查到那個表的統計量。
如果,覺得這個值不夠精確,想要更精確的,那就效仿這種方法,自己建立一個表存儲表名和表對應的總量(可以稱為計數器),每次取總量的時候就直接查這個表的欄位就可以了,當然那個百萬表在做增刪的時候記得加減這個計數器。離線算好
本人隱隱約約記得阿里的Java開發手冊推薦count(*)這種寫法,但在可能為空的column上作count(*)結果會過濾掉column=null的結果,不同的業務需求會有不同的寫法。
關於題主的問題,不知道你的count(*)語句帶不帶where條件,不帶條件查全表記錄數很簡單,直接
select count(*) from xxx
或者直接從information_schema查詢。
帶條件那就應該屬於普通查詢語句的優化。和是不是count(*)應該沒多大關係,主要是避免全表掃描,在查詢條件的欄位上建立索引是比較好的解決方法。另外不同的資料庫引擎count(*)效率也不一樣,關於MySQL的查詢優化CSDN上也有很多經驗,如查詢條件應該盡量避免group by,大規模數據分頁查詢limit的優化等。多自行嘗試寫些SQL,就我自己的經驗來看查詢效率低下主要兩個原因:
- 查詢欄位沒有建索引
- SQL寫法有問題,換個寫法往往能解決
經驗之談,沒什麼理論性,希望能對你有幫助
加hint
推薦閱讀:
※sql 查詢如何將結果集 輸出為一段字元串?
※沒有任何基礎的人怎麼學SQL?
※PostgreSQL 有哪些經典入門書籍?
※如何評價cmu-db的peloton資料庫?
※從編程語言設計的角度,如何評價SQL語言?