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

MySQL?中的count(*)?與?count(1)?誰更快一些?

 更新時間:2022年02月22日 09:47:31   作者:碼農小宋  
這篇文章主要討論MySQL?中?count(*)?與?count(1)?誰更快一些?以下討論基于?InnoDB?存儲引擎,并且再文末單獨說一下MyISAM?,感興趣的小伙伴可以參考一下

先說結論:這兩個性能差別不大。

1.實踐

我準備了一張有 100W 條數(shù)據(jù)的表,表結構如下:

CREATE TABLE `user` (
? `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
? `username` varchar(255) DEFAULT NULL,
? `address` varchar(255) DEFAULT NULL,
? `password` varchar(255) DEFAULT NULL,
? PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

可以看到,有一個主鍵索引。我們來用兩種方式統(tǒng)計一下表中的記錄數(shù),如下:

可以看到,兩條 SQL 的執(zhí)行效率其實差不多,都是 0.14s。

再來看另外兩個統(tǒng)計:

id 是主鍵,username 以及 address 則是普通字段??梢钥闯?,用 id 來統(tǒng)計,也有一丟丟優(yōu)勢。松哥這里因為測試數(shù)據(jù)樣板比較小,所以效果不明顯,小伙伴們可以加大測試數(shù)據(jù)量,那么這種差異會更加明顯。

那么到底是什么原因造成的這種差異,接下來我們就來簡單分析一下。

2. explain 分析

我們先用 explain 來看下這幾個 SQL 不同的執(zhí)行計劃:

可以看到,前三個統(tǒng)計方式的執(zhí)行計劃是一樣的,后面兩個是一樣的。我這里和大家比較下 explain 中的不同項:

  • type:前三個的 type 值為 index,表示全索引掃描,就是把整個索引過一遍就行(注意是索引不是整個表);后兩個的 type 值為 all,表示全表掃描,即不會使用索引。
  • key:這個表示 MySQL 決定采用哪個索引來優(yōu)化對該表的訪問,PRIMARY 表示利用主鍵索引,NULL 表示不用索引。
  • key_len:這個表示 MySQL 使用的鍵長度,因為我們的主鍵類型是 INT 且非空,所以值為 4。
  • Extra:這個中的 Using index 表示優(yōu)化器只需要通過訪問索引就可以獲取到需要的數(shù)據(jù)(不需要回表)。

通過 explain 我們其實也能大概看出來前三種統(tǒng)計方式的執(zhí)行效率是要高一些的(因為用到了索引),而后面兩種的統(tǒng)計效率相對來說要低一些的(沒用索引,需要全表掃描)。僅有上面的分析還不夠,我們再來從原理角度來分析一下。

3. 原理分析

3.1 主鍵索引與普通索引

在開始原理分析以前,我想先帶領大家看一下 B+ 樹,這對于我們理解接下來的內容有重要作用。大家都知道,InnoDB 中索引的存儲結構都是 B+ 樹(至于什么是 B+ 樹,和 B 樹有什么區(qū)別,這個本文就不討論了,這兩個單獨都能整出來一篇文章),主鍵索引和普通索引的存儲又有所不同,

如下圖表示主鍵索引:

可以看到,在主鍵索引中,葉子結點保存了每一行的數(shù)據(jù)。而在普通索引中,葉子結點保存的是主鍵值,當我們使用普通索引去搜索數(shù)據(jù)的時候,先在葉子結點中找到主鍵,再拿著主鍵去主鍵索引中查找數(shù)據(jù),相當于做了兩次查找,這也就是我們平常所說的回表操作。

3.2 原理分析

不知道小伙伴們有沒有注意過,我們學習 MySQL 的時候,count 函數(shù)是歸在聚合函數(shù)那一類的,就是 avg、sum 等,count 函數(shù)和這些歸在一起,說明它也是一個聚合函數(shù)。既然是聚合函數(shù),那么就需要對返回的結果集進行一行行的判斷,這里就涉及到一個問題,返回的結果是啥?我們分別來看:對于? ??select count(1) from user;?? ?這個查詢來說,InnoDB 引擎會去找到一個最小的索引樹去遍歷(不一定是主鍵索引),但是不會讀取數(shù)據(jù),而是讀到一個葉子節(jié)點,就返回 1,最后將結果累加。對于? ??select count(id) from user;?? ? 這個查詢來說,InnoDB 引擎會遍歷整個主鍵索引,然后讀取 id 并返回,不過因為 id 是主鍵,就在 B+ 樹的葉子節(jié)點上,所以這個過程不會涉及到隨機 IO(并不需要回表等操作去數(shù)據(jù)頁拿數(shù)據(jù)),性能也是 OK 的。對于???select count(username) from user;?? ? 這個查詢來說,InnoDB 引擎會遍歷整張表做全表掃描,讀取每一行的 username 字段并返回,如果 username 在定義時候設置了 not null,那么直接統(tǒng)計 username 的個數(shù);如果 username 在定義的時候沒有設置 not null,那么就先判斷一下 username 是否為空,然后再統(tǒng)計。最后再來說說? ??select count(*) from user;?? ?,這個 SQL 的特殊之處在于它被 MySQL 優(yōu)化過,當 MySQL 看到 ??count(*)?? ?就知道你是想統(tǒng)計總記錄數(shù),就會去找到一個最小的索引樹去遍歷,然后統(tǒng)計記錄數(shù)。因為主鍵索引(聚集索引)的葉子節(jié)點是數(shù)據(jù),而普通索引的葉子節(jié)點則是主鍵值,所以普通索引的索引樹要小一些。然而在上文的案例中,我們只有主鍵索引,所以最終使用的就是主鍵索引?,F(xiàn)在,如果我修改上面的表,為 username 字段也添加索引,然后我們再來看? ??explain select count(*) from user;?? ?的執(zhí)行計劃:

可以看到,此時使用的索引就是 username 索引了,和我們前面的分析結果是一致的。從上面的描述中我們就可以看出,第一個查詢性能最高,第二個次之(因為需要讀取 id 并返回),第三個最差(因為需要全表掃描),第四個的查詢性能則接近第一個。

4. MyISAM 呢?

可能有小伙伴知道,MyISAM 引擎中的? ??select count(*) from user;?? ?操作執(zhí)行起來是非??斓?,那是因為 MyISAM 把表中的行數(shù)直接存在磁盤中了,需要的時候直接讀取出來就行了,所以非???。MyISAM 引擎之所以這樣做,主要是因為它是不支持事務的,所以它的統(tǒng)計實際上就非常容易,添加一行記錄一行就行了。而我們常用的 InnoDB 卻不能這樣做!為啥?因為 InnoDB 支持事務!為了支持事務,InnoDB 引入了 MVCC 多版本并發(fā)控制,所以在數(shù)據(jù)讀取的時候可能會有臟讀、幻讀以及不可重復讀等問題。所以,InnoDB 需要將每一行數(shù)據(jù)拿出來,判斷該行數(shù)據(jù)對當前會話是否可見,如果可見,就統(tǒng)計該行數(shù)據(jù),否則不予統(tǒng)計。

到此這篇關于MySQL 中 count(*) 與 count(1) 誰更快一些?的文章就介紹到這了,更多相關MySQL 中 count(*) 與 count(1) 內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 詳細介紹windows下MySQL安裝教程

    詳細介紹windows下MySQL安裝教程

    這篇文章主要給大家介紹的是windows下MySQL安裝教程,其實好多公司,數(shù)據(jù)庫的面試題都是不可避免的,甚至一些前端工程師面試的時候都避免不了被詢問到和數(shù)據(jù)庫有關的一些問題。下面就從最基礎的安裝教程開始,需要的朋友可以參考一下
    2021-11-11
  • MySQL優(yōu)化方案參考

    MySQL優(yōu)化方案參考

    今天小編就為大家分享一篇關于MySQL優(yōu)化方案參考,小編覺得內容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • MySQL如何清空慢查詢文件

    MySQL如何清空慢查詢文件

    這篇文章主要介紹了MySQL如何清空慢查詢文件,如何在線生成一個新的慢查詢文件,感興趣的小伙伴們可以參考一下
    2015-12-12
  • MySQL 刪除數(shù)據(jù)庫中重復數(shù)據(jù)方法小結

    MySQL 刪除數(shù)據(jù)庫中重復數(shù)據(jù)方法小結

    在實際項目中,我們經常會遇到刪除數(shù)據(jù)庫中重復數(shù)據(jù)的問題,貌似是很簡單的問題哈,下面我們來探討下
    2014-07-07
  • Ubuntu 18.04下mysql 8.0 安裝配置方法圖文教程

    Ubuntu 18.04下mysql 8.0 安裝配置方法圖文教程

    這篇文章主要為大家詳細介紹了Ubuntu 18.04下mysql 8.0 安裝配置方法圖文教程,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-05-05
  • Mysql自增主鍵id不是以此逐級遞增的處理

    Mysql自增主鍵id不是以此逐級遞增的處理

    這篇文章主要介紹了Mysql自增主鍵id不是以此逐級遞增的處理方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • mysql表分區(qū)的方式和實現(xiàn)代碼示例

    mysql表分區(qū)的方式和實現(xiàn)代碼示例

    通俗地講表分區(qū)是將一個大表,根據(jù)條件分割成若干個小表,下面這篇文章主要給大家介紹了關于mysql表分區(qū)的方式和實現(xiàn)代碼,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-02-02
  • mysql的日期和時間函數(shù)大全

    mysql的日期和時間函數(shù)大全

    mysql的日期和時間函數(shù) 這里是一個使用日期函數(shù)的例子。下面的查詢選擇所有 date_col 值在最后 30 天內的記錄。
    2008-04-04
  • MySQL查看主從狀態(tài)的命令實現(xiàn)

    MySQL查看主從狀態(tài)的命令實現(xiàn)

    本文主要介紹了MySQL查看主從狀態(tài)的命令實現(xiàn),我們可以使用SHOW SLAVE STATUS命令來查看主從狀態(tài),本文就來詳細的介紹一下如何實現(xiàn),感興趣的可以了解一下
    2023-10-10
  • MySQL數(shù)據(jù)庫事務隔離級別詳解

    MySQL數(shù)據(jù)庫事務隔離級別詳解

    這篇文章主要介紹了MySQL數(shù)據(jù)庫事務隔離級別詳解的相關資料,需要的朋友可以參考下
    2017-03-03

最新評論