国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

MYSQL統計行數時到底應該怎么COUNT

Anonymous1 / 2961人閱讀

摘要:會話在插入一條新數據,在查詢時的結果是時會話語句已經提交,所以在會話的事務中能看到這個更新。由于會話在時事務還沒有提交,會話看不到會話的更新,所以會話在時的結果是。

相信每個人在寫代碼時都有遇到過要獲取MYSQL表里數據行數的情況,多數人獲取數據表行數時都用COUNT(*),但同時也流傳了不少其他方式,比如說COUNT(1)、COUNT(主鍵)、COUNT(字段)。到底哪種方式MYSQL執行起來更快也是眾說紛紜,其實之前我也不知道到底哪個執行起來快,到底誰說的對(笑哭)。好在最近在認真學習極客時間的MySQL專欄,其中專門有一節是對這個問題的討論,看完后也是解除了長久以來的疑惑。

文章中都是針對MySQL的InnoDB引擎展開討論的,MyISAM引擎是把一個表的總行數記錄在了磁盤里,查詢時效率很高(如果加了where條件也不能直接從磁盤返回)。而InnoDB由于多版本并發控制(MVCC)的原因,即使時同一時刻的查詢InnoDB表應該"返回多少行"也是不確定的,比如假設表t中有10000行數據:

時刻 會話A 會話B 會話C
T1 begin;
T2 select count(*) from t;
T3 insert into t (插入一行);
T4 begin;
T5 insert into t (插入一行);
T6 select count(*) from t; (返回10000) select count(*) from t; (返回10002); select count(*) from t; (返回10001)

會話A在T1開啟事務拿到一致性視圖,可重復讀級別下在事務中任何時刻讀到數據都一樣,其他事務的更新對會話A沒影響所以count(*)的結果是10000,會話B在T4開啟事務拿到一致性視圖,T4之前會話C已經新插入了一條語句并提交(多帶帶執行一條更新語句,InnoDB會自己啟動一個事務,語句執行完馬上提交)。會話B在T5插入一條新數據,在T6查詢時count(*)的結果是10002(T4 begin時會話C insert語句已經提交,所以在會話B的事務中能看到這個更新)。由于會話B在T6時事務還沒有提交,會話C看不到會話B的更新,所以會話C在T6時count(*)的結果是10001。

COUNT是一個聚合函數,它的功能是對返回的結果集中每一行進行判斷,如果COUNT函數的參數不是NULL則累加1,否則不累加,最后返回累計值。接下來看一下每個COUNT版本的執行效率:

COUNT(主鍵ID) InnoDB遍歷全表,把每一行的主鍵值都取出來返回給MySQL的Server層,因為主鍵不可能為NULL,Server層直接按行累加最后返回累計值給客戶端。

COUNT(1) 遍歷全表但不取值,Server層對返回的每一行放個數字"1"進去,按行累加。COUNT(1)比COUNT(主鍵)快,因為不需要取值,減少了數據傳輸。

COUNT(字段) 遍歷全表,一行行從記錄中讀出字段值給Server層,Server層判斷值不為NULL了再累加。

COUNT(*) MySQL專門做了優化,會找到表中最小的索引樹,InnoDB普通索引樹比主鍵索引小很多,對于COUNT(*)遍歷哪個樹是一樣的,count(*)時MySQL不取記錄值,count(*)也肯定不為NULL,Server層中直接按行累加。

所以這個版本COUNT的從低到高分別為:

COUNT(字段) < COUNT(主鍵) < COUNT(1)COUNT(*)

所以建議你盡量使用count(*)來獲取記錄行數。

另外要注意,很多人為了銷量會把表的行數記錄到Redis中,但這樣不能保證Redis里的計數和MySQL表里的數據保持精確一致,這是兩個不同的存儲系統不支持分布式事務所以就無法拿到精確的一致性視圖,如果為了效率把表行數多帶帶存儲那么最好存放在一個多帶帶的MySQL表里,這樣無法拿到一致性視圖的問題就能解決了。

關于MySQL更詳細的分析,推薦關注MySQL實戰45講

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/17983.html

相關文章

發表評論

0條評論

Anonymous1

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<