深入了解MySQL中索引優(yōu)化器的工作原理
本文導讀
本文將解讀MySQL數據庫查詢優(yōu)化器(CBO)的工作原理。簡單介紹了MySQL Server的組成,MySQL優(yōu)化器選擇索引額原理以及SQL成本分析,最后通過 select 查詢總結整個查詢過程。
一、MySQL 優(yōu)化器是如何選擇索引的
下面我們來看這張表,SUB_ODR_ID字段創(chuàng)建了相關的 2 個索引,根據我們前面所學我們建立一個PRIMARY KEY (ID)自增主鍵索引,(LOG_ID, SUB_ODR_ID)設置為聯合索引、唯一索引,兩個時間CREATE_TIME、UPDATE_TIME分別設置兩個索引。
CREATE TABLE `***` ( `ID` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主鍵id', `LOG_ID` varchar(32) NOT NULL COMMENT '交易流水號', `ODR_ID` varchar(32) NOT NULL COMMENT '父單號', `SUB_ODR_ID` varchar(32) NOT NULL COMMENT '子單號', `CREATE_TIME` datetime(0) NOT NULL COMMENT '創(chuàng)建時間', `CREATE_BY` varchar(32) NOT NULL COMMENT ' 創(chuàng)建人', `UPDATE_TIME` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '更新時間', `UPDATE_BY` varchar(32) NOT NULL COMMENT '更新人', PRIMARY KEY (`ID`) USING BTREE, UNIQUE INDEX `UNQ_LOG_SUBODR_ID`(`LOG_ID`, `SUB_ODR_ID`) USING BTREE, INDEX `IDX_ODR_ID`(`ODR_ID`) USING BTREE, INDEX `IDX_SUB_ID`(`SUB_ODR_ID`) USING BTREE, INDEX `IDX_CREATE_TIME`(`CREATE_TIME`) USING BTREE, INDEX `IDX_UPDATE_TIME`(`UPDATE_TIME`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 1 SET = utf8 COLLATE = utf8_general_ci COMMENT = '分攤業(yè)務明細表' ROW_FORMAT = Dynamic;
在查詢字段 SUB_ODR_ID 中,理論上可以使用三個相關的索引:UNQ_LOG_SUBODR_ID、IDX_SUB_ID,MySQL優(yōu)化器如何從這三個索引中進行選擇?
在關系數據庫中,B+樹只是用于存儲的數據結構。
如何使用它取決于數據庫的優(yōu)化器。優(yōu)化器確定特定索引的選擇,即執(zhí)行計劃。優(yōu)化器的選擇基于成本,成本越低,首選指數越高。
1、MySQL數據庫組成
MySQL數據庫由Server(服務器)層和Engine(引擎)層組成。
Serve層有SQL分析器、SQL優(yōu)化器和SQL執(zhí)行器,負責SQL語句的具體執(zhí)行過程。
Engine層負責存儲特定數據,例如最常用的InnoDB存儲引擎,以及用于在內存中存儲臨時結果集的TempTable引擎。
SQL優(yōu)化器將分析所有可能的執(zhí)行計劃,并選擇成本最低的執(zhí)行。這個優(yōu)化器被稱為CBO(基于成本的優(yōu)化器)。
2、MySQL數據庫成本計算
在 MySQL中,一條 SQL 的計算成本計算,很好理解,就是訪問數據庫(數據庫頁、磁盤)+處理數據。
CPU成本,表示計算成本,例如索引鍵值的比較、記錄值的比較和結果集的排序。這些操作都在服務器層完成
IO成本,表示引擎級IO的成本,MySQL 8.0可以通過區(qū)分表的數據是否在內存中來分別計算讀取內存IO和磁盤IO的成本。
Cost = Server Cost + Engine Cost = CPU Cost + IO Cost
MySQL優(yōu)化器認為,如果一段SQL需要創(chuàng)建一個基于磁盤的臨時表,那么此時的成本是最大的,是基于內存的臨時表的20倍。比較索引鍵值和記錄的成本很低,但如果要比較的記錄很多,成本就會非常大。
MySQL 優(yōu)化器認為,從磁盤讀取的開銷是內存開銷的 4 倍(成本不是一成不變的會根據硬件變化)。
二、MySQL查詢成本
查看各成本的值,MySQL優(yōu)化器的工作原理,我們執(zhí)行下面這行SQL語句,分析執(zhí)行過程,MySQL 索引選擇是基于 SQL 執(zhí)行成本
EXPLAIN FORMAT=json select * from test.fork_business_detail f where f.sub_odr_id = ''
read_cost表示從InnoDB存儲引擎讀取的成本;
eval_cost表示服務器層的CPU成本;
prefix_cost表示SQL的總成本;
data_read_per_join 表示讀取記錄中的字節(jié)總數。
{ "query_block": { "cost_info": { "query_cost": "1.20" }, "table": { "access_type": "ref", "possible_keys": [ "IDX_SUB_ID" ], "key": "IDX_SUB_ID", "used_key_parts": [ "SUB_ODR_ID" ], "key_length": "98", "ref": [ "const" ], "cost_info": { "read_cost": "1.00", "eval_cost": "0.20", "prefix_cost": "1.20", "data_read_per_join": "1K" }, "used_columns": [ "ID", "LOG_ID", "ODR_ID", "SUB_ODR_ID", "CREATE_TIME", "CREATE_BY", "UPDATE_TIME", "UPDATE_BY" ] } } }
三、SELECT 執(zhí)行過程
如何提高MySQL的查詢性能?首先,您需要了解查詢優(yōu)化器進行SQL處理的整個過程。SELECT SQL 的執(zhí)行過程為例,如下圖所示:
客戶端向服務器發(fā)送SELECT查詢;服務器首先檢查查詢緩存。如果緩存被命中,存儲在緩存中的結果將立即返回。否則,進入下一階段;
服務器執(zhí)行SQL解析、預處理,查詢優(yōu)化器生成相應的執(zhí)行計劃;MySQL根據優(yōu)化器生成的執(zhí)行計劃調用存儲引擎的API執(zhí)行查詢;結果將返回到客戶端,并同時放入查詢緩存。
總結
本文解讀了MySQL數據庫查詢優(yōu)化器(CBO)的工作原理。簡單介紹了MySQL Server的組成,MySQL優(yōu)化器選擇索引額原理以及SQL成本分析,最后通過 select 查詢總結整個查詢過程。
到此這篇關于深入了解MySQL中索引優(yōu)化器的工作原理的文章就介紹到這了,更多相關MySQL索引優(yōu)化器內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
監(jiān)控MySQL主從狀態(tài)的shell腳本
這篇文章主要分享了監(jiān)控MySQL主從狀態(tài)的shell腳本,幫助大家更好的監(jiān)控mysql數據庫,保持穩(wěn)定性,感興趣的朋友可以了解下2020-12-12解決大于5.7版本mysql的分組報錯Expression #1 of SELECT list is not in GR
這篇文章主要介紹了解決大于5.7版本mysql的分組報錯Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated問題,需要的朋友可以參考下2019-10-10Mysql及Navicat中設置字段自動填充當前時間及修改時間實現
這篇文章主要給大家介紹了關于Mysql及Navicat中設置字段自動填充當前時間及修改時間實現的相關資料,文中通過實例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2023-07-07