MySQL中的count(*)?和?count(1)?區(qū)別性能對比分析
1前言
我們本節(jié)來看看我們常說的索引下推。
2什么是索引下推
索引下推(Index Condition Pushdown,簡稱ICP),是MySQL5.6版本的新特性,用于優(yōu)化數(shù)據(jù)查詢。
不使用索引條件下推優(yōu)化時存儲引擎通過索引檢索到數(shù)據(jù),然后返回給MySQL服務(wù)器,服務(wù)器然后判斷數(shù)據(jù)是否符合條件。
當(dāng)使用索引條件下推優(yōu)化時,如果存在某些被索引的列的判斷條件時,MySQL服務(wù)器將這一部分判斷條件傳遞給存儲引擎,然后由存儲引擎通過判斷索引是否符合MySQL服務(wù)器傳遞的條件,只有當(dāng)索引符合條件時才會將數(shù)據(jù)檢索出來返回給MySQL服務(wù)器。
索引條件下推優(yōu)化可以減少存儲引擎查詢基礎(chǔ)表的次數(shù),也可以減少M(fèi)ySQL服務(wù)器從存儲引擎接收數(shù)據(jù)的次數(shù)。
換句話說:索引下推能減少回表查詢次數(shù),提高查詢效率。
3索引下推優(yōu)化的原理
我們先簡單了解一下MySQL大概的架構(gòu):
MySQL從上至下分為以下幾層:
- MySQL服務(wù)層:包括NoSQL和SQL接口、查詢解析器、優(yōu)化器、緩存和Buffer等組件。
- 存儲引擎層:各種插件式的表格存儲引擎,實現(xiàn)事務(wù)、索引等各種存儲引擎相關(guān)的特性。
- 文件系統(tǒng)層: 讀寫物理文件。
MySQL服務(wù)層負(fù)責(zé)SQL語法解析、生成執(zhí)行計劃等,并調(diào)用存儲引擎層去執(zhí)行數(shù)據(jù)的存儲和檢索。
索引下推的下推其實就是指將部分上層(服務(wù)層)負(fù)責(zé)的事情,交給了下層(引擎層)去處理。
我們來具體看一下,在沒有使用ICP的情況下,MySQL的查詢:
- 獲取下一行,首先讀取索引信息,然后根據(jù)索引將整行數(shù)據(jù)讀取出來。
- 然后通過where條件判斷當(dāng)前數(shù)據(jù)是否符合條件,符合返回數(shù)據(jù)。
使用ICP的情況下,查詢過程:
- 獲取下一行的索引信息。
- 檢查索引中存儲的列信息是否符合索引條件,如果符合將整行數(shù)據(jù)讀取出來,如果不符合跳過讀取下一行。
- 用剩余的判斷條件,判斷此行數(shù)據(jù)是否符合要求,符合要求返回數(shù)據(jù)。
4索引下推適用條件
- 需要整表掃描的情況。比如:range, ref, eq_ref, ref_or_null 。
- 適用于InnoDB 引擎和 MyISAM 引擎的查詢。(5.6版本不適用分區(qū)表查詢,5.7版本后可以用于分區(qū)表查詢)。
- 對于InnDB引擎只適用于二級索引,因為InnDB的聚簇索引會將整行數(shù)據(jù)讀到InnDB的緩沖區(qū),這樣一來索引條件下推的主要目的減少IO次數(shù)就失去了意義。因為數(shù)據(jù)已經(jīng)在內(nèi)存中了,不再需要去讀取了。
- 引用子查詢的條件不能下推。
- 調(diào)用存儲過程的條件不能下推,存儲引擎無法調(diào)用位于MySQL服務(wù)器中的存儲過程。
- 觸發(fā)條件不能下推。
5EXPLAN分析
當(dāng)使用explan進(jìn)行分析時,如果使用了索引條件下推,Extra會顯示Using index condition。并不是Using index。
因為并不能確定利用索引條件下推查詢出的數(shù)據(jù)就是符合要求的數(shù)據(jù),還需要通過其他的查詢條件來判斷。
6索引下推的具體實踐
理論比較抽象,我們來上一個實踐。使用一張用戶表tuser,表里創(chuàng)建聯(lián)合索引(name, age)。
如果現(xiàn)在有一個需求:檢索出表中名字第一個字是張,而且年齡是10歲的所有用戶。那么,SQL語句是這么寫的:
select * from tuser where name like '張%' and age=10;
假如你了解索引最左匹配原則,那么就知道這個語句在搜索索引樹的時候,只能用 張,找到的第一個滿足條件的記錄id為1。
那接下來的步驟是什么呢?
沒有使用ICP
在MySQL 5.6之前,存儲引擎根據(jù)通過聯(lián)合索引找到name likelike '張%' 的主鍵id(1、4),逐一進(jìn)行回表掃描,去聚簇索引找到完整的行記錄,server層再對數(shù)據(jù)根據(jù)age=10進(jìn)行篩選。我們看一下示意圖:
可以看到需要回表兩次,把我們聯(lián)合索引的另一個字段age浪費(fèi)了。
使用ICP
而MySQL 5.6 以后, 存儲引擎根據(jù)(name,age)聯(lián)合索引,找到,由于聯(lián)合索引中包含列,所以存儲引擎直接再聯(lián)合索引里按照age=10過濾。按照過濾后的數(shù)據(jù)再一一進(jìn)行回表掃描。我們看一下示意圖:
可以看到只回表了一次。
除此之外我們還可以看一下執(zhí)行計劃,看到Extra一列里 Using index condition,這就是用到了索引下推。
+----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-----------------------+| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra || 1 | SIMPLE | tuser | NULL | range | na_index | na_index | 102 | NULL | 2 | 25.00 | Using index condition |
7相關(guān)系統(tǒng)參數(shù)
索引條件下推默認(rèn)是開啟的,可以使用系統(tǒng)參數(shù)optimizer_switch來控制器是否開啟。
查看默認(rèn)狀態(tài):
mysql> select @@optimizer_switch\G; index_merge=on, index_merge_union=on, index_merge_sort_union=on, index_merge_intersection=on, engine_condition_pushdown=on, index_condition_pushdown=on, mrr=on, mrr_cost_based=on, block_nested_loop=on, batched_key_access=off, materialization=on, semijoin=on, loosescan=on, firstmatch=on, duplicateweedout=on, subquery_materialization_cost_based=on, use_index_extensions=on, condition_fanout_filter=on, derived_merge=on
切換狀態(tài):
set ="index_condition_pushdown=off"; set ="index_condition_pushdown=on";
8小結(jié)
索引下推優(yōu)化技術(shù)其實就是充分利用了索引中的數(shù)據(jù),盡量在查詢出整行數(shù)據(jù)之前過濾掉無效的數(shù)據(jù)。
由于需要存儲引擎將索引中的數(shù)據(jù)與條件進(jìn)行判斷,所以這個技術(shù)是基于存儲引擎的,只有特定引擎可以使用。并且判斷條件需要是在存儲引擎這個層面可以進(jìn)行的操作才可以,比如調(diào)用存儲過程的條件就不可以,因為存儲引擎沒有調(diào)用存儲過程的能力。
到此這篇關(guān)于MySQL中的count(*) 和 count(1) 區(qū)別性能對比的文章就介紹到這了,更多相關(guān)mysql count(*) 和 count(1)區(qū)別內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
關(guān)于MySql 10038錯誤的完美解決方法(三種)
本文給大家?guī)砣N有關(guān)mysql報10038錯誤的解決方法,每種方法都非常不錯,需要的朋友參考下2016-09-09Mysql5.7.18版本(二進(jìn)制包安裝)自定義安裝路徑教程詳解
這篇文章主要介紹了Mysql5.7.18版本(二進(jìn)制包安裝)自定義安裝路徑教程詳解,需要的朋友可以參考下2017-07-07MySQL數(shù)據(jù)備份之mysqldump的使用方法
mysqldump常用于MySQL數(shù)據(jù)庫邏輯備份,這篇文章主要給大家介紹了關(guān)于MySQL數(shù)據(jù)備份之mysqldump使用的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下2021-11-11MySQL中動態(tài)生成SQL語句去掉所有字段的空格的操作方法
在數(shù)據(jù)庫管理過程中,我們常常會遇到需要對表中字段進(jìn)行清洗和整理的情況,本文將詳細(xì)介紹如何在MySQL中動態(tài)生成SQL語句來去掉所有字段的空格,感興趣的朋友一起看看吧2025-04-04Mysql中FIND_IN_SET()和IN區(qū)別簡析
這篇文章主要介紹了Mysql中FIND_IN_SET()和IN區(qū)別簡析,設(shè)計實例代碼,具有一定參考價值。需要的朋友可以了解。2017-10-10