1. 程式人生 > 其它 >【MySQL學習筆記(十一)】之基於成本的單表查詢優化計算與連線查詢的優化計算

【MySQL學習筆記(十一)】之基於成本的單表查詢優化計算與連線查詢的優化計算

技術標籤:MYSQLmysql資料庫索引

本文章由公號【開發小鴿】釋出!歡迎關注!!!


老規矩–妹妹鎮樓:

一. 基於成本的優化

(一) 概述

所謂查詢語句的執行成本由兩個方面組成,一個是I/O成本,經常使用的InnoDB和MyISAM儲存引擎都是將資料和索引儲存到磁碟上,當查詢表中的記錄時,需要先把資料或者索引載入到記憶體中,然後再進行操作,從磁碟到記憶體的時間成本為I/O成本;還有一個是CPU成本,讀取記錄以及檢測記錄是否滿足對應的搜尋條件等操作的時間成本為CPU成本。

InnoDB讀取一個頁面花費的成本預設是1.0,讀取一個記錄以及檢測一條記錄是否符合搜尋條件的成本預設是0.2,這些數字稱為成本常數。


(二) 優化步驟

MySQL的優化器會找出所有可以用來執行該語句的方案,在對比這些方案後找出成本最低的方案,即執行計劃,之後才會呼叫儲存引擎提供的介面執行查詢。

1. 根據搜尋條件,找出所有可能使用的索引

根據所有的搜尋條件,來判斷是否可以生成合適的掃描區間,進而得到可能使用的索引。

2. 計算全表掃描的代價

對於InnoDB來說,全表掃描就是將聚簇索引中的記錄都一次與給定的搜尋條件進行比較,並將符合搜尋條件的記錄加入到結果集中。所以需要將聚簇索引對應的頁面載入到記憶體中,然後再檢測記錄是否符合搜尋條件。查詢成本=I/O成本+CPU成本,因此計算全表掃描的代價時需要兩個資訊:聚簇索引佔用的頁面數與該表中的記錄數。

通過查詢表的統計資訊,得到表中的記錄數與表佔用的儲存空間位元組數。

SHOW TABLE STATUS LILKE ‘表名’;

Rows表示表中的記錄數,Data_length表示表佔用的位元組數,對於MyISAM來說是資料檔案的大小,對於InnoDB來說是聚簇索引的大小,可以除以16KB得出聚簇索引的頁面數量。之後,計算I/O成本:

I/O成本 = 聚簇索引頁面數量 x 1.0 + 1.1 

1.0表示磁碟載入到記憶體的成本常數,1.1是微調值;

CPU成本 = 記錄數 x 0.2 + 1.0

0.2是讀取記錄以及檢測記錄的成本常數,1.0 是微調值

3. 計算使用不同索引執行查詢的代價

分析單獨使用不同的索引執行查詢的代價,最後還要分析是否能夠使用索引合併。一般使用的都是二級索引+回表方式執行的查詢,在計算這種查詢的成本時依賴兩個資料:掃描區間的數量與需要回表的記錄數。無論某個掃描區間的二級索引佔用了幾個頁面,查詢優化器粗暴地認為I/O成本與讀取一個頁面的成本相同。

根據回表的記錄的主鍵值到聚簇索引中執行回表操作,MySQL中評估回表成本時認為每次回表相當於訪問一個頁面,即有多少條記錄就有多少次頁面I/O。回表得到完整的使用者記錄,再檢測其他搜尋條件是否成立即可,檢測也是用讀取記錄與檢測記錄的成本計算。

最後對不同索引查詢得到的二級索引記錄是否按照主鍵排序,來決定是否索引合併。

4. 對比各種執行方案的代價,找出成本最低的方案

對比全表,不同索引的查詢代價,使用最低成本的即可。


(三) 連線查詢的成本

1. 條件過濾

連線查詢的查詢成本由兩部分組成:單詞查詢驅動表的成本以及多次查詢被驅動表的成本。將查詢驅動表後得到的記錄條數稱為驅動表的扇出。在兩種情況下計算驅動表扇出值時需要經過猜測,一種是使用全表掃描的方式執行單表查詢,另一種是使用索引單表查詢,猜測滿則搜尋條件的記錄數。這種猜測過程稱為條件過濾。

2. 兩表連線查詢成本分析

連線查詢的成本 = 單次訪問驅動表成本 + 驅動表扇出值 x 單次訪問被驅動表成本

對於左連線和右連線,驅動表是固定的,所以只需要為驅動表和被驅動表選擇成本最低的訪問方法,即可得到最優的查詢方案。而對於內連線,驅動表與被驅動表的順序可以互換,因此需要考慮最優的表連線順序,然後再選擇訪問方法。這樣的話,就需要為每一種連線順序進行成本計算分析了。

可以看到,連線查詢的優化目標就是儘量減少驅動表的扇出,以及訪問被驅動表的成本要儘量的低。實際使用各種,降低訪問被驅動表的成本最有效,如在被驅動表的連線列上建立索引,這樣就可以使用ref訪問方法了,最好情況下,使用主鍵或者唯一二級索引列,使用const訪問方法。

3. 多表連線查詢成本分析

對於n個表的連線查詢,確實有n!中連線順序,也確實都要計算一遍成本,MySQL中有很多優化這種因計算不同連線順序下的查詢成本而帶來的效能損耗的方法。

(1) 提前結束某種連線順序的成本計算

MySQL在計算各種連線順序的成本之前,維護一個全域性變數,表示當前最小的連線查詢成本,只要某種連線順序的成本超過了它,就continue退出到下一個連線順序了。


(2) 系統變數optimizer_search_depth

為了防止無窮盡地分析各種順序,設定了該系統變數,相當於一個上限值,如果連線表的個數小於該值,就窮舉分析每一種連線順序,否則只窮舉分析與該值相同的表。