mysql 更新时间加数字_Mysql实战45讲笔记:8、聚合函数count
count(*)的實現方式
在不同的MySQL引擎中,count()有不同的實現方式 1. MyISAM引擎把一個表的總行數存在了磁盤上,因此執行count()的時候會直接返回這個數,效率很高; 2. 而InnoDB引擎就麻煩了,它執行count(*)的時候,需要把數據一行一行地從引擎里面讀出來,然后累積計數。
以上是沒有過濾條件的count(*),如果加了where 條件的話,MyISAM表也是不能返回得這么快的。為什么InnoDB不跟MyISAM一樣,也把數字存起來呢?
因為即使是在同一個時刻的多個查詢,由
于多版本并發控制(MVCC)的原因,InnoDB表“應該返回多少行”也是不確定的
假設表t中現在有10000條記錄,我們設計了三個用戶并行的會話。
- 會話A先啟動事務并查詢一次表的總行數;
- 會話B啟動事務,插入一行后記錄后,查詢表的總行數
- 會話C先啟動一個單獨的語句,插入一行記錄后,查詢表的總行數。
我們假設從上到下是按照時間順序執行的,同一行語句是在同一時刻執行的, 在最后一個時刻,三個會話A、B、C會同時查詢表t的總行數,但拿到的結果卻不同。
這和InnoDB的事務設計有關系,可重復讀是它默認的隔離級別,在代碼上就是通過多版本并發控制,也就是MVCC來實現的。每一行記錄都要判斷自己是否對這個會話可見,因此對于count(*)請求來說,InnoDB只好把數據一行一行地讀出依次判斷,可見的行才能夠用于計算“基于這個查詢”的表的總行數。
不過MySQL在執行count(*)操作的時候還是做了優化: MySQL優化器會找到最小的那棵樹來遍歷。在保證邏輯正確的前提下,盡量減少掃描的數據量,是數據庫系統設計的通用法則之一
小結: MyISAM表雖然count()很快,但是不支持事務; show table status命令雖然返回很快,但是不準確; InnoDB表直接count(*)會遍歷全表,雖然結果準確,但會導致性能問題。
用緩存系統保存計數
對于更新很頻繁的庫來說,可能會第一時間想到,用緩存系統來支持。 用一個Redis服務來保存這個表的總行數。這個表每被插入一行Redis計數就加1,每被刪除一行Redis計數就減1。這種方式下,讀和更新操作都很快,但是這種方式存在問題:可能會丟失更新
Redis的數據不能永久地留在內存里,所以會把這個值定期地持久化存儲起來。但即使這樣,仍然可能丟失更新。試想如果剛剛在數據表中插入了一行,Redis中保存的值也加了1,然后Redis異常重啟了,重啟后要從存儲redis數據的地方把這個值讀回來,而剛剛加1的這個計數操作卻丟失了。
雖然這個場景可以解決:在Redis異常重啟以后,到數據庫里面單獨執行一次count(*)獲取真實的行數,再把這個值寫回到Redis里。異常重啟畢竟不是經常出現的情況,這一次全表掃描的成本,還是可以接受的。 不過,將計數保存在緩存系統中的方式,還不只是丟失更新的問題。即使Redis正常工作,這個值還是邏輯上不精確的。
如果要顯示操作記錄的總數,同時還要顯示最近操作的100條記錄。那么,這個頁面的邏輯就需要先到Redis里面取出計數,再到數據表里面取數據記錄。
我們是這么定義不精確的:
- 一種是,查到的100行結果里面有最新插入記錄,而Redis的計數里還沒加1;
- 另一種是,查到的100行結果里沒有最新插入的記錄,而Redis的計數里已經加了1。
這兩種情況,都是邏輯不一致的。
在并發系統里面,無法精確控制不同線程的執行時刻的,因為存在圖中的這種操作序列,所以,即使Redis正常工作,這個計數值還是邏輯上不精確的。
在數據庫保存計數
如果我們把這個計數直接放到數據庫里單獨的一張計數表C中,又會怎么樣呢?
首先,這解決了崩潰丟失的問題,InnoDB是支持崩潰恢復不丟數據的。 其次,由于InnoDB是支持事務的,所以從下圖可以看出邏輯上是一致的
不同的count用法
count()是一個聚合函數,對于返回的結果集,一行行地判斷,如果count函數的參數不是NULL,累計值就加1,否則不加。最后返回累計值。- count(*)、count(主鍵id)和count(1) 都表示返回滿足條件的結果集的總行數;
- count(字段),則表示返回滿足條件的數據行里面,參數“字段”不為NULL的總個數。
- 對于count(主鍵id)來說:InnoDB引擎會遍歷整張表,把每一行的id值都取出來,返回給server層。server層拿到id后,判斷是不可能為空的,就按行累加。
- 對于count(1)來說,InnoDB引擎遍歷整張表,但不取值。server層對于返回的每一行,放一個數字“1”進去,判斷是不可能為空的,按行累加。
總結
以上是生活随笔為你收集整理的mysql 更新时间加数字_Mysql实战45讲笔记:8、聚合函数count的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 最终幻想安卓版下载(最终幻想安卓版)
- 下一篇: linux命令上网(linux 科学上网