MySQL5.7官方文檔翻譯--優化器成本模型

成本模型,也有叫做代價模型,原文是Cost Model,下面翻譯都使用成本模型

 

8.9.5 優化器的成本模型

SQL查詢的方式多種多樣,MySQL的優化器使用基於對查詢成本進行預估的成本模型來生成執行方案。優化器擁有一系列編譯過的“成本常量”來決定使用怎樣的執行方案。

除了編譯過的成本常量之外,優化器在構建執行方案的時候還會用到一個數據庫,也是用來做成本評估的。這些成本評估用的數據保存在mysql的系統庫(庫名是mysql),server_cost表和engine_cost表中,這兩個表中的數據項是隨時可以修改的。這些表存在的意義就是讓優化器在準備執行方案的時候可以比較簡單的判斷查詢成本。

1,成本模型的基本操作

2,成本模型的數據庫

3,成本模型數據庫的修改方式

 

成本模型的基本工作方式

這些可配置的成本模型是這樣工作的:

1,SQL服務在啓動的時候從成本模型的數據庫表中讀取數據,存到內存,運行期間就從內存中讀取這些數據。這個表中非NULL的值的優先級高於編譯好的默認值,這個表中的NULL值代表優化器使用編譯好的默認值。

2,SQL服務運行的時候可能會重新讀取成本表。重新讀取的場景有:存儲引擎的動態加載,和執行FLUSH OPTIMIZER_COSTS語句。

3,內存中的成本評估數據對於客戶端的會話(session)來說是實時的,貫串了會話的開始到結束。注意,如果SQL服務重新讀取了成本表,表中修改的信息只對後面生成的會話生效,對即將結束的會話不會起作用。

4,成本評估表是對指定的SQL服務實例生效的,SQL服務不會把成本評估表的修改同步到從庫去。 


成本模型表

優化器的成本模型表包含兩張表,在mysql的系統庫(庫名是mysql)中,表中保存了查詢的時候需要用到的成本評估的信息。

1,server_cost。服務通用的成本評估信息表。

2,engine_cost。特定存儲引擎的成本評估信息表。


server_cost表包含以下字段:

1,cost_name

成本評估的時候用的名字。這個名字是非大小寫敏感的。如果當SQL服務讀取這個表的時候發現了自己不認識的名字,會在錯誤日誌中記錄一條警告日誌。

2,cost_value

成本評估項的具體值。如果這個值是非NULL的,SQL服務就會使用這個值,否則SQL服務會使用默認值(編譯好的值)。數據庫管理員可以通過修改這個值來影響成本評估的結果。如果當SQL服務讀取這個表時發現值是非法的(比如負數),會在錯誤日誌中記錄一條警告日誌。

如果想要覆蓋系統默認值(往往成本評估表裏沒有這一條記錄),把這個值改成非NULL就可以了。如果想要恢復使用系統默認值,就把這個值改回NULL就可以。然後要執行FLUSH OPTIMIZER_COSTS語句,然後SQL服務會重新讀取這些成本模型表。

3,last_update

該行數據的上次更新時間。

4,comment

該項評估信息的備註。數據庫管理員可以在這一欄寫備註,比如爲什麼要設置這麼個值等等。

 server_cost表的主鍵是cost_name字段,所以cost_name肯定不會重複。


server_cost表的cost_name字段可以有這些值:

1,disk_temptable_create_cost(默認 40.0), disk_temptable_row_cost (默認 1.0)

在基於磁盤的存儲引擎中建立臨時表時的成本評估值(比如InnoDB和MyISAM)。如果這些值增大,優化器會認爲建立臨時表的成本增大,從而減少使用臨時表。關於臨時表的更多信息參見章節8.4.4, “Internal Temporary Table Use in MySQL”。

如果這些磁盤相關參數大於內存相關參數(比如memory_temptable_create_cost, memory_temptable_row_cost)的話,代表處理磁盤上的臨時表有着更多的成本。

2,key_compare_cost (默認 0.1)

比較記錄中關鍵字時的成本。如果這個值增大,代表在查詢計劃中,比較多種關鍵字這種操作的成本增大了。比如,和使用索引而避免排序的查詢計劃相比,文件索引(filesort)的成本變的相對更高了。

3,memory_temptable_create_cost(默認 2.0), memory_temptable_row_cost (默認 0.2)

在基於內存的存儲引擎(比如MEMORY)中建立臨時表時的成本評估值。如果這些值增大,優化器會認爲建立臨時表的成本增大,從而減少使用臨時表。關於臨時表的更多信息參見章節8.4.4, “Internal Temporary Table Use in MySQL”。

如果這些內存相關參數小於磁盤相關參數(比如disk_temptable_create_cost, disk_temptable_row_cost)的話,代表處理內存上的表有着更少的成本。

4,row_evaluate_cost (默認0.2)

評估查詢條件的成本。如果這個值增大,代表查詢更多行的執行計劃的成本變得更大了。比如,和範圍查詢相比,全表掃描的成本相對變得更大了。

 

engine_cost表包含以下字段:

1,engine_name

成本評估的時候用的名字。這個名字是非大小寫敏感的。如果這個值是default,那些沒有配置自己名字的存儲引擎都會使用這個參數。如果當SQL服務讀取這個表的時候發現了自己不認識的名字,會在錯誤日誌中記錄一條警告日誌。

2,device_type

成本評估生效的設備類型。這一欄是爲了區別不同的磁盤設備而設計的,比如區分傳統的硬盤和固態硬盤。目前這一欄還沒有用到,值也只能設爲0。

3,cost_name

和server_cost表中功能一樣。

4,cost_value

和server_cost表中功能一樣。

4,last_update

和server_cost表中功能一樣。

5,comment

和server_cost表中功能一樣。

engine_cost表的主鍵是一個聯合索引,包含了cost_name,engine_name,device_type列,所以這些列組成的聯合鍵值是不會重複的。


engine_cost表中的cost_name可以有以下值:

1,io_block_read_cost (默認1.0)

從磁盤上讀取一個索引塊或數據塊的成本。如果這個值增大,代表讀取多個硬盤塊的查詢計劃變得成本更高了。比如,和範圍查詢相比,全表掃描的成本相對變得更大了。

2, memory_block_read_cost (默認1.0)

和io_block_read_cost差不多,只不過這個值代表從內存數據庫中讀取數據塊時的成本。

如果io_block_read_cost和memory_block_read_cost的值不一樣,那麼即使是同一個查詢,執行兩次sql時的執行計劃也會不一樣。假設訪問內存的成本比訪問磁盤的成本低,那麼,數據加載到緩衝池之前執行sql和第二次執行該sql相比得到的執行計劃就可能不同,因爲第二次執行的時候數據已經在緩衝池裏了。


修改成本評估模型的數據庫

如果數據庫管理員要修改成本模型的值,建議加倍或者減半這些值,然後看看效果。

對io_block_read_cost和memory_block_read_cost的修改可能效果是最好的。這兩個參數可以讓成本模型的數據讀取模塊決定從磁盤讀數據還是從內存讀數據。比如,在其他設置都一樣的情況下,如果把io_block_read_cost設置的比memory_block_read_cost大,那麼優化器會更願意選擇從內存中讀取數據的執行計劃,而不是從磁盤中讀取數據的執行計劃。

下面舉個例子,怎樣修改io_block_read_cost的默認值:

UPDATE mysql.engine_cost

 SET cost_value = 2.0

 WHERE cost_name = 'io_block_read_cost';

FLUSH OPTIMIZER_COSTS;
下面舉個例子,怎樣修改InnoDB引擎的io_block_read_cost的默認值:

INSERT INTO mysql.engine_cost

 VALUES ('InnoDB', 0, 'io_block_read_cost', 3.0,

 CURRENT_TIMESTAMP, 'Using a slower disk for InnoDB');

FLUSH OPTIMIZER_COSTS;

以上就是MySQL官網對於優化器成本模型一章的翻譯,MySQL版本5.7,章節是8.9.5。

不知道5.7的文檔有沒有人翻譯過,鑑於英語水平有限,要是有翻譯不準確的地方歡迎指正。

官方文檔中這個章節的地址:https://dev.mysql.com/doc/refman/5.7/en/cost-model.html#cost-model-operation

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章