標籤:

請教一下大家,關於 MySQL 百萬數據量的 count(*) 查詢如何優化?


-------------8月19日更正 加粗部分----------------

1.sql語句本身優化

使用select count(1)或者select count(主鍵)這樣的方式

這個優化對於mysql不成立,感謝評論中兩位指正

select count(1)和select count(*)是等價的,但是count(col)不同,即使col是主鍵

以下查詢數據全部取自內存中,innodb engine

mysql&> select count(id) from sbtest1 where c ="xxxxxxx";

+-----------+

| count(id) |

+-----------+

| 0 |

+-----------+

1 row in set (10.33 sec)

用主鍵的查詢用時會更長,如果這裡的col是一個允許為NULL的值,查詢時間會更長

mysql&> select count(1) from sbtest1 where c ="xxxxxxx";

+----------+

| count(1) |

+----------+

| 0 |

+----------+

1 row in set (9.85 sec)

mysql&> select count(*) from sbtest1 where c ="xxxxxxx";

+----------+

| 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,就我自己的經驗來看查詢效率低下主要兩個原因:

  1. 查詢欄位沒有建索引
  2. SQL寫法有問題,換個寫法往往能解決

經驗之談,沒什麼理論性,希望能對你有幫助


加hint


推薦閱讀:

sql 查詢如何將結果集 輸出為一段字元串?
沒有任何基礎的人怎麼學SQL?
PostgreSQL 有哪些經典入門書籍?
如何評價cmu-db的peloton資料庫?
從編程語言設計的角度,如何評價SQL語言?

TAG:SQL | MySQL |