亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

MySQL select count(*)計數很慢優(yōu)化方案

 更新時間:2022年08月11日 08:44:37   作者:一燈架構???????  
這篇文章主要介紹了MySQL select count(*)計數很慢優(yōu)化方案,文章圍繞主題展開詳細的內容介紹,具有一定的參考價值,需要的小伙伴可以參考一下

前言

在日常開發(fā)工作中,我經常會遇到需要統(tǒng)計總數的場景,比如:統(tǒng)計訂單總數、統(tǒng)計用戶總數等。一般我們會使用MySQL 的count函數進行統(tǒng)計,但是隨著數據量逐漸增大,統(tǒng)計耗時也越來越長,最后竟然出現慢查詢的情況,這究竟是什么原因呢?本篇文章帶你一下學習一下。

1. MyISAM存儲引擎計數為什么這么快?

我們總有個錯覺,就是感覺MyISAM引擎的count計數要比InnoDB引擎更快,實際這不是錯覺。

MyISAM引擎把表的總行數單獨記錄在磁盤上,查詢的時候可以直接返回,不需要再累加統(tǒng)計。

但是當SQL查詢中有where條件的時候,就無法再使用表的總行數了,還是需要乖乖的進行累加統(tǒng)計,查詢性能也就跟InnoDB相差無幾了。

為什么MyISAM引擎能夠記錄表的總行數,InnoDB引擎卻不行?

因為MyISAM引擎不支持事務,只有表鎖,所以記錄的總行數是準確的。

而InnoDB引擎支持事務和行鎖,存在并發(fā)修改的情況。又由于事務的隔離性,會出現不可重復讀和幻讀,記錄的總行數無法保證是準確的。

2. 能不能手動實現統(tǒng)計總行數

既然InnoDB引擎沒有幫我們記錄總行數,我們能不能手動記錄總行數,比如使用Redis。

其實也是不行的,使用Redis記錄總行數,至少有下面3個問題:

  • 無法實現事務之間的隔離
  • 更新丟失,因為i++不是原子操作,當然可以使用Lua腳本實現原子操作,更復雜。
  • Redis是非關系型緩存數據庫,不能當作關系型持久化數據庫使用,一般需要設置過期時間。

由上圖中得知,雖然Redis計數加1操作放在了事務里面,但是不受事務控制的,在事務沒有提交前,其他查詢依然讀到了最新的總行數,這就是臟讀的情況。

3. InnoDB引擎能否實現快速計數

有一種辦法,可以粗略估計表的總行數,就是使用MySQL命令:

show table status like 'user';

真實的總行數有100萬行,預估有99萬多行,誤差在可接受的范圍內。

部分場景適用,比如粗略估計網站的總用戶數。

4. 四種計數方式的性能差別

常見的統(tǒng)計總行數的方式有以下四種:

count(*) 、 count(常量) 、 count(id) 、 count(字段)

InnoDB引擎對count計數做了優(yōu)化,會選用數據量較小的非聚簇索引進行統(tǒng)計。

比如用戶表中有三個索引,分別是主鍵索引、name索引和age索引,使用執(zhí)行計劃查看計數的時候用到了哪個索引?

CREATE TABLE `user` (
 ?`id` int NOT NULL AUTO_INCREMENT COMMENT '主鍵',
 ?`name` varchar(100) DEFAULT NULL COMMENT '姓名',
 ?`age` tinyint NOT NULL,
 ?PRIMARY KEY (`id`),
 ?KEY `idx_name` (`name`),
 ?KEY `idx_age` (`age`)
) ENGINE=InnoDB COMMENT='用戶表';
explain select count(*) from user;

用到了數據量較小的age索引。

count(*) 、 count(常量) 是直接統(tǒng)計表中的總行數,效率較高。

而 count(id) 還需要把數據返回給MySQL Server端進行累加計數。

最后 count(字段)需要篩選不為null字段,效率最差。

四種計數的查詢性能從高到低,依次是:

count(*) ≈ count(常量) > count(id) > count(字段)

對于大多數情況,得到計數結果,還是老老實實使用count(*)

所以推薦使用select count(*) ,別跟select * 搞混了,不推薦使用select * 的。

到此這篇關于MySQL select count(*)計數很慢優(yōu)化方案的文章就介紹到這了,更多相關MySQL 優(yōu)化內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • You must SET PASSWORD before executing this statement的解決方法

    You must SET PASSWORD before execut

    今天在MySql5.6操作時報錯:You must SET PASSWORD before executing this statement解決方法,需要的朋友可以參考下
    2013-06-06
  • mysql could not be resolved: Name or service not known

    mysql could not be resolved: Name or service not known

    今天查看mysql日志的時候發(fā)現[Warning] IP address '10.0.0.220' could not be resolved: Name or service not known,原來是mysql DNS反解:skip-name-resolve的原因,屏蔽一下就可以了
    2015-08-08
  • 記一次Mysql不走日期字段索引的原因小結

    記一次Mysql不走日期字段索引的原因小結

    本文主要介紹了記一次Mysql不走日期字段索引的原因,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • 詳解MySQL批量入庫的幾種方式

    詳解MySQL批量入庫的幾種方式

    本文主要介紹了詳解MySQL批量入庫的幾種方式,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-02-02
  • MySQL8的主要目錄結構解讀

    MySQL8的主要目錄結構解讀

    這篇文章主要介紹了MySQL8的主要目錄結構,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • 一臺電腦(windows系統(tǒng))安裝兩個版本MYSQL方法步驟

    一臺電腦(windows系統(tǒng))安裝兩個版本MYSQL方法步驟

    由于新舊項目數據庫版本差距太大,編碼格式不同,引擎也不同,所以只好裝兩個數據庫,這篇文章主要給大家介紹了關于一臺電腦(windows系統(tǒng))安裝兩個版本MYSQL的方法步驟,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2023-03-03
  • MySQL多表查詢詳解上

    MySQL多表查詢詳解上

    這篇文章主要介紹了MySQL多表查詢詳解上,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-07-07
  • MySQL教程數據定義語言DDL示例詳解

    MySQL教程數據定義語言DDL示例詳解

    這篇文章主要為大家介紹了MySQL教程中什么是數據定義語言DDL的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步
    2021-10-10
  • 詳解MySQL實時同步到Oracle解決方案

    詳解MySQL實時同步到Oracle解決方案

    這篇文章主要介紹了詳解MySQL實時同步到Oracle解決方案,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-03-03
  • MySQL中binlog備份腳本的方法

    MySQL中binlog備份腳本的方法

    這篇文章主要介紹了MySQL中binlog備份腳本分享,這里主要介紹一下我寫的MySQL二進制日志的備份腳本,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-04-04

最新評論