欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

淺談MySQL 統(tǒng)計(jì)行數(shù)的 count

 更新時(shí)間:2020年07月15日 15:51:54   作者:以終為始  
這篇文章主要介紹了MySQL 統(tǒng)計(jì)行數(shù)的 count的相關(guān)資料,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下

MySQL count() 函數(shù)我們并不陌生,用來統(tǒng)計(jì)每張表的行數(shù)。但如果你的表越來越大,且是 InnoDB 引擎的話,會(huì)發(fā)現(xiàn)計(jì)算的速度會(huì)越來越慢。在這篇文章里,會(huì)先介紹 count() 實(shí)現(xiàn)的原理及原因,然后是 count 不同用法的性能分析,最后給出需要頻繁改變并需要統(tǒng)計(jì)表行數(shù)的解決方案。

Count() 的實(shí)現(xiàn)

InnoDB 和 MyISAM 是 MySQL 常用的數(shù)據(jù)引擎,由于兩者實(shí)現(xiàn)的不同,導(dǎo)致 count() 操作計(jì)算的效率也不同。

對于 MyISAM 來說,它把每個(gè)表的總行數(shù)都存在了磁盤上,因此使用 count(*) 計(jì)算時(shí),效率很高直接返回結(jié)果。但如果加入了 where 條件,依然會(huì)進(jìn)行搜索,所以效率是不高的。

對于 InnoDB 來說,在進(jìn)行 count(*) 運(yùn)算時(shí),會(huì)把數(shù)據(jù)從引擎中一行行讀出來,然后累計(jì)計(jì)數(shù),自然表大了之后,效率就變低了。

那么,為什么 InnoDB 不能像 MyISAM 在表中記錄呢?原因就在于 InnoDB 比 MyISAM 多了支持事務(wù)的特性,同時(shí)也需要一定的取舍。由于 MVCC 的控制,使得 MySQL 具有并發(fā)的能力,也就是說對于同一時(shí)刻,InnoDB 返回的表的行數(shù)是不一定的,事務(wù)看到的行數(shù)與開啟后的一致性視圖有關(guān),換句話說,每個(gè)事務(wù)能看到的數(shù)據(jù)版本是不一樣的,只能一行行拿出來進(jìn)行判斷。

像下面的事務(wù),假設(shè)表 t 有 10000 條數(shù)據(jù):

Session A Session B Session C
select count(*) from t;
insert into t ();
begin;
insert into t();
select count(*) from t; select count(*) from t; select count(*) from t;
10000; 結(jié)果是 10002 結(jié)果是 10001

對于 Session A 來說,Session B 未提交不可見,Session C 提交了,但是在 Session A 啟動(dòng)后提交的,也不可見。所以是 10000.

而對于 Session B 而言,Session C 在啟動(dòng)之前提交,自己又插入了一條,所以結(jié)果是 10002.

其實(shí) InnoDB 在進(jìn)行 count(*) 操作時(shí),還是做了優(yōu)化的,在進(jìn)行 count(*) 操作時(shí),由于普通索引會(huì)保存主鍵的 id 值,所以會(huì)找到最小的那顆普通索引樹進(jìn)行查找,而不是去遍歷主鍵索引樹。

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

另外在使用 show table status 時(shí),也可以查詢出行數(shù),而且速度很快,但需要注意的是,該命令是通過索引統(tǒng)計(jì)的值來采樣估算的。官方文檔說誤差可以有 40%-50%.

但如果我們真的需要實(shí)時(shí)的獲取的某個(gè)表的行數(shù),應(yīng)該怎么辦呢?

手動(dòng)保存表的數(shù)量

用緩存系統(tǒng)來保存計(jì)數(shù)

對于進(jìn)行更新的表,可能會(huì)想到用緩存系統(tǒng)來支持。比如 Redis 里來保存某個(gè)表總行數(shù)。

每次插入數(shù)據(jù)庫時(shí),Redis 計(jì)數(shù)加一,相反則減一,這樣看起來讀寫操作都很快,但會(huì)存在一些問題。

緩存系統(tǒng)會(huì)丟失更新:

對于 Redis 在內(nèi)存中的數(shù)據(jù),需要定期的同步到磁盤中,但對于 Redis 異常重啟,就沒有辦法了。比如在 Redis 中插入后,Redis 重啟,數(shù)據(jù)沒有持久化到硬盤。這時(shí)可以在重啟 Redis 后,從數(shù)據(jù)庫執(zhí)行下 count(*) 操作,然后更新到 Redis 中。一次全表掃描還是可行的。

邏輯不精確:

假設(shè)一個(gè)頁面中,需要顯示一張表的行數(shù),以及每一條數(shù)據(jù)。在實(shí)現(xiàn)時(shí),可以先從 Redis 取數(shù)量,然后從數(shù)據(jù)庫里取記錄。

但可能會(huì)出現(xiàn)這樣的情況:

  1. 數(shù)據(jù)庫查到 100 行結(jié)果里有最新插入的記錄,而 Redis 計(jì)數(shù)里少 1.
  2. 數(shù)據(jù)庫查到 100 行結(jié)果沒有最新的記錄,但 Redis 計(jì)數(shù)卻多了 1.
Session A Session B
插入一條數(shù)據(jù); T1
讀 Redis 計(jì)數(shù); T2
從數(shù)據(jù)庫中查記錄;
Redis 計(jì)數(shù)加 1; T3

對于 Session B 來說,在 T2 時(shí)刻,會(huì)發(fā)現(xiàn) Redis 的數(shù)量比數(shù)據(jù)庫少 1 條。

Session A Session B
Redis 計(jì)數(shù)加 1; T1
讀 Redis 計(jì)數(shù); T2
從數(shù)據(jù)庫中查記錄;
插入一條數(shù)據(jù); T3

對于 Session B 來說,在 T2 時(shí)刻,會(huì)發(fā)現(xiàn) Redis 的數(shù)量比數(shù)據(jù)庫多 1 條。

其實(shí)產(chǎn)生問題的原因就是因?yàn)?Redis 和數(shù)據(jù)庫查記錄沒有在同一個(gè)事務(wù)中。

用數(shù)據(jù)庫保存

由于 InnoDB 引擎的支持,MySQL 本身是支持事務(wù)的,所以將 Redis 的插入操作換成在數(shù)據(jù)庫的更新操作,就可以利用在RR級別下的事務(wù)特性,進(jìn)而保證數(shù)據(jù)的精確性。

而且還有一點(diǎn),由于 redo log 的支持,在 MySQL 發(fā)生異常時(shí),是可以保證 crash-safe。

不同 count 用法的執(zhí)行效率

count() 本身是一個(gè)聚合函數(shù),對于返回的結(jié)果集,一行行地判斷。如果參數(shù)不是 NULL 的話,會(huì)一直累加,最后返回結(jié)果。

所以 count(*), count(id), count(1) 表示都是返回滿足條件的結(jié)果集總行數(shù)。

而 count(字段),則表示滿足條件的數(shù)據(jù)行里,不為 NULL 的字段。

對于 count(id) 來說,InnoDB 會(huì)遍歷整張表,把每行 id 取出來,給 server 層。Server 判斷 id 是否為空,然后累加。

對于 count(1) 來說,InnoDB 會(huì)遍歷整張表,但不取值。Server 層會(huì)自己放入 1,然后累加。

所以對于 count(1) 的執(zhí)行會(huì)比 count(*) 要快,少了解析數(shù)據(jù)行以及拷貝字段值的操作。

對于 count(字段) 來說,如果字段定義時(shí)是 not null, 會(huì)一行行讀出,并判斷不能為 null,然后累加。如果定義時(shí)可以為 null,執(zhí)行時(shí),需要將值去除,判斷不是 null 才累加。

count(*) 除外,專門做了優(yōu)化,不取值,直接按行累加,并且會(huì)找到最小的索引樹進(jìn)行計(jì)算。

總結(jié)

MySQL count() 函數(shù)的執(zhí)行效率和底層的數(shù)據(jù)引擎有關(guān)。MyISAM 不加 where 條件,查詢會(huì)很快,但不支持事務(wù)。InnoDB 支持事務(wù),由于 MVCC 的實(shí)現(xiàn),導(dǎo)致每次查詢都需要一行行的掃描,效率不高。

解決方法可以通過設(shè)計(jì)外部緩存如 Redis,保存記錄。但存在異常重啟和數(shù)據(jù)不準(zhǔn)確的情況。可以通過在 InnoDB 中新建一張表,保存記錄這樣的解決方案。

最后,InnoDB 對 count(*) 做了獨(dú)立的優(yōu)化,而其他的 count 操作,則需要額外的操作。

以上就是淺談MySQL 統(tǒng)計(jì)行數(shù)的 count的詳細(xì)內(nèi)容,更多關(guān)于Mysql count的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • MySQL如何解決幻讀問題

    MySQL如何解決幻讀問題

    在高并發(fā)數(shù)據(jù)庫系統(tǒng)中,需要保證事務(wù)與事務(wù)之間的隔離性,還有事務(wù)本身的一致性。所以需要解決幻讀問題,本文就來介紹一下,感興趣的可以了解一下
    2021-08-08
  • Mysql查詢數(shù)據(jù)庫或數(shù)據(jù)表中的數(shù)據(jù)量以及數(shù)據(jù)大小

    Mysql查詢數(shù)據(jù)庫或數(shù)據(jù)表中的數(shù)據(jù)量以及數(shù)據(jù)大小

    許多數(shù)據(jù)庫的元數(shù)據(jù)都是存儲(chǔ)在mysql中的,本文主要介紹了Mysql查詢數(shù)據(jù)庫或數(shù)據(jù)表中的數(shù)據(jù)量以及數(shù)據(jù)大小,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-02-02
  • MySQL數(shù)據(jù)庫跨版本遷移的實(shí)現(xiàn)三種方式

    MySQL數(shù)據(jù)庫跨版本遷移的實(shí)現(xiàn)三種方式

    本文主要介紹了MySQL數(shù)據(jù)庫跨版本遷移的實(shí)現(xiàn),主要包含mysqldump,物理文件遷移和原地升級三種,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-05-05
  • windows下如何解決mysql secure_file_priv null問題

    windows下如何解決mysql secure_file_priv null問題

    這篇文章主要介紹了windows下如何解決mysql secure_file_priv null問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • mysql 5.7.13 解壓縮版(免安裝)安裝配置教程

    mysql 5.7.13 解壓縮版(免安裝)安裝配置教程

    這篇文章主要介紹了MySQL 5.7.13 for Windows解壓縮版(免安裝)安裝配置教程,感興趣的小伙伴們可以參考一下
    2016-06-06
  • MySQL登錄、訪問及退出操作實(shí)戰(zhàn)指南

    MySQL登錄、訪問及退出操作實(shí)戰(zhàn)指南

    當(dāng)我們要使用mysql時(shí),一定要了解mysql的登錄、訪問及退出,下面這篇文章主要給大家介紹了關(guān)于MySQL登錄、訪問及退出操作的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-10-10
  • MySQL 分表分庫怎么進(jìn)行數(shù)據(jù)切分

    MySQL 分表分庫怎么進(jìn)行數(shù)據(jù)切分

    這篇文章主要介紹了MySQL 分表分庫怎么進(jìn)行數(shù)據(jù)切分,幫助大家更好的理解和學(xué)習(xí)使用MySQL,感興趣的朋友可以了解下
    2021-03-03
  • mysql 8.0.21免安裝版配置方法圖文教程

    mysql 8.0.21免安裝版配置方法圖文教程

    這篇文章主要為大家詳細(xì)介紹了mysql 8.0.21免安裝版配置教程,文中安裝步驟介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-07-07
  • MYSQL將表名稱修改成大寫的存儲(chǔ)過程

    MYSQL將表名稱修改成大寫的存儲(chǔ)過程

    這篇文章主要為大家詳細(xì)介紹了MYSQL將表名稱修改成大寫的存儲(chǔ)過程,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-08-08
  • MySQL 5.7常見數(shù)據(jù)類型

    MySQL 5.7常見數(shù)據(jù)類型

    這篇文章主要介紹了MySQL 5.7數(shù)據(jù)類型詳解,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-07-07

最新評論