日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

mysql 5.7 hint_新特性解读 | MySQL 8.0 新增 HINT 模式

發(fā)布時間:2024/9/27 数据库 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql 5.7 hint_新特性解读 | MySQL 8.0 新增 HINT 模式 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

在開始演示之前,我們先介紹下兩個概念。

概念一,數(shù)據(jù)的可選擇性基數(shù),也就是常說的cardinality值。

查詢優(yōu)化器在生成各種執(zhí)行計劃之前,得先從統(tǒng)計信息中取得相關(guān)數(shù)據(jù),這樣才能估算每步操作所涉及到的記錄數(shù),而這個相關(guān)數(shù)據(jù)就是cardinality。簡單來說,就是每個值在每個字段中的唯一值分布狀態(tài)。

比如表t1有100行記錄,其中一列為f1。f1中唯一值的個數(shù)可以是100個,也可以是1個,當(dāng)然也可以是1到100之間的任何一個數(shù)字。這里唯一值越的多少,就是這個列的可選擇基數(shù)。

那看到這里我們就明白了,為什么要在基數(shù)高的字段上建立索引,而基數(shù)低的的字段建立索引反而沒有全表掃描來的快。當(dāng)然這個只是一方面,至于更深入的探討就不在我這篇探討的范圍了。

概念二,關(guān)于HINT的使用。

這里我來說下HINT是什么,在什么時候用。

HINT簡單來說就是在某些特定的場景下人工協(xié)助MySQL優(yōu)化器的工作,使她生成最優(yōu)的執(zhí)行計劃。一般來說,優(yōu)化器的執(zhí)行計劃都是最優(yōu)化的,不過在某些特定場景下,執(zhí)行計劃可能不是最優(yōu)化。

比如:表t1經(jīng)過大量的頻繁更新操作,(UPDATE,DELETE,INSERT),cardinality已經(jīng)很不準(zhǔn)確了,這時候剛好執(zhí)行了一條SQL,那么有可能這條SQL的執(zhí)行計劃就不是最優(yōu)的。為什么說有可能呢?

來看下具體演示

譬如,以下兩條SQL,A:select?*?from?t1?where?f1?=?20;B:select?*?from?t1?where?f1?=?30;

如果f1的值剛好頻繁更新的值為30,并且沒有達(dá)到MySQL自動更新cardinality值的臨界值或者說用戶設(shè)置了手動更新又或者用戶減少了sample page等等,那么對這兩條語句來說,可能不準(zhǔn)確的就是B了。

這里順帶說下,MySQL提供了自動更新和手動更新表cardinality值的方法,因篇幅有限,需要的可以查閱手冊。

那回到正題上,MySQL 8.0 帶來了幾個HINT,我今天就舉個index_merge的例子。

示例表結(jié)構(gòu):mysql>?desc?t1;+------------+--------------+------+-----+---------+----------------+|?Field??????|?Type?????????|?Null?|?Key?|?Default?|?Extra??????????|+------------+--------------+------+-----+---------+----------------+|?id?????????|?int(11)??????|?NO???|?PRI?|?NULL????|?auto_increment?||?rank1??????|?int(11)??????|?YES??|?MUL?|?NULL????|????????????????||?rank2??????|?int(11)??????|?YES??|?MUL?|?NULL????|????????????????||?log_time???|?datetime?????|?YES??|?MUL?|?NULL????|????????????????||?prefix_uid?|?varchar(100)?|?YES??|?????|?NULL????|????????????????||?desc1??????|?text?????????|?YES??|?????|?NULL????|????????????????||?rank3??????|?int(11)??????|?YES??|?MUL?|?NULL????|????????????????|+------------+--------------+------+-----+---------+----------------+7?rows?in?set?(0.00?sec)

表記錄數(shù):mysql>?select?count(*)?from?t1;+----------+|?count(*)?|+----------+|????32768?|+----------+1?row?in?set?(0.01?sec)

這里我們兩條經(jīng)典的SQL:SQL C:select?*?from?t1?where?rank1?=?1?or?rank2?=?2?or?rank3?=?2;SQL D:select?*?from?t1?where?rank1?=100??and?rank2?=100??and?rank3?=100;

表t1實際上在rank1,rank2,rank3三列上分別有一個二級索引。

那我們來看SQL C的查詢計劃。

顯然,沒有用到任何索引,掃描的行數(shù)為32034,cost為3243.65。mysql>?explain??format=json?select?*?from?t1??where?rank1?=1?or?rank2?=?2?or?rank3?=?2\G***************************?1.?row?***************************EXPLAIN:?{??"query_block":?{????"select_id":?1,????"cost_info":?{??????"query_cost":?"3243.65"????},????"table":?{??????"table_name":?"t1",??????"access_type":?"ALL",??????"possible_keys":?[????????"idx_rank1",????????"idx_rank2",????????"idx_rank3"??????],??????"rows_examined_per_scan":?32034,??????"rows_produced_per_join":?115,??????"filtered":?"0.36",??????"cost_info":?{????????"read_cost":?"3232.07",????????"eval_cost":?"11.58",????????"prefix_cost":?"3243.65",????????"data_read_per_join":?"49K"??????},??????"used_columns":?[????????"id",????????"rank1",????????"rank2",????????"log_time",????????"prefix_uid",????????"desc1",????????"rank3"??????],??????"attached_condition":?"((`ytt`.`t1`.`rank1`?=?1)?or?(`ytt`.`t1`.`rank2`?=?2)?or?(`ytt`.`t1`.`rank3`?=?2))"????}??}}1?row?in?set,?1?warning?(0.00?sec)

我們加上hint給相同的查詢,再次看看查詢計劃。

這個時候用到了index_merge,union了三個列。掃描的行數(shù)為1103,cost為441.09,明顯比之前的快了好幾倍。mysql>?explain??format=json?select?/*+?index_merge(t1)?*/?*?from?t1??where?rank1?=1?or?rank2?=?2?or?rank3?=?2\G***************************?1.?row?***************************EXPLAIN:?{??"query_block":?{????"select_id":?1,????"cost_info":?{??????"query_cost":?"441.09"????},????"table":?{??????"table_name":?"t1",??????"access_type":?"index_merge",??????"possible_keys":?[????????"idx_rank1",????????"idx_rank2",????????"idx_rank3"??????],??????"key":?"union(idx_rank1,idx_rank2,idx_rank3)",??????"key_length":?"5,5,5",??????"rows_examined_per_scan":?1103,??????"rows_produced_per_join":?1103,??????"filtered":?"100.00",??????"cost_info":?{????????"read_cost":?"330.79",????????"eval_cost":?"110.30",????????"prefix_cost":?"441.09",????????"data_read_per_join":?"473K"??????},??????"used_columns":?[????????"id",????????"rank1",????????"rank2",????????"log_time",????????"prefix_uid",????????"desc1",????????"rank3"??????],??????"attached_condition":?"((`ytt`.`t1`.`rank1`?=?1)?or?(`ytt`.`t1`.`rank2`?=?2)?or?(`ytt`.`t1`.`rank3`?=?2))"????}??}}1?row?in?set,?1?warning?(0.00?sec)

我們再看下SQL D的計劃:不加HINT,mysql>?explain?format=json?select?*?from?t1?where?rank1?=100?and?rank2?=100?and?rank3?=100\G***************************?1.?row?***************************EXPLAIN:?{??"query_block":?{????"select_id":?1,????"cost_info":?{??????"query_cost":?"534.34"????},????"table":?{??????"table_name":?"t1",??????"access_type":?"ref",??????"possible_keys":?[????????"idx_rank1",????????"idx_rank2",????????"idx_rank3"??????],??????"key":?"idx_rank1",??????"used_key_parts":?[????????"rank1"??????],??????"key_length":?"5",??????"ref":?[????????"const"??????],??????"rows_examined_per_scan":?555,??????"rows_produced_per_join":?0,??????"filtered":?"0.07",??????"cost_info":?{????????"read_cost":?"478.84",????????"eval_cost":?"0.04",????????"prefix_cost":?"534.34",????????"data_read_per_join":?"176"??????},??????"used_columns":?[????????"id",????????"rank1",????????"rank2",????????"log_time",????????"prefix_uid",????????"desc1",????????"rank3"??????],??????"attached_condition":?"((`ytt`.`t1`.`rank3`?=?100)?and?(`ytt`.`t1`.`rank2`?=?100))"????}??}}1?row?in?set,?1?warning?(0.00?sec)加了HINT,mysql>?explain?format=json?select?/*+?index_merge(t1)*/?*?from?t1?where?rank1?=100?and?rank2?=100?and?rank3?=100\G***************************?1.?row?***************************EXPLAIN:?{??"query_block":?{????"select_id":?1,????"cost_info":?{??????"query_cost":?"5.23"????},????"table":?{??????"table_name":?"t1",??????"access_type":?"index_merge",??????"possible_keys":?[????????"idx_rank1",????????"idx_rank2",????????"idx_rank3"??????],??????"key":?"intersect(idx_rank1,idx_rank2,idx_rank3)",??????"key_length":?"5,5,5",??????"rows_examined_per_scan":?1,??????"rows_produced_per_join":?1,??????"filtered":?"100.00",??????"cost_info":?{????????"read_cost":?"5.13",????????"eval_cost":?"0.10",????????"prefix_cost":?"5.23",????????"data_read_per_join":?"440"??????},??????"used_columns":?[????????"id",????????"rank1",????????"rank2",????????"log_time",????????"prefix_uid",????????"desc1",????????"rank3"??????],??????"attached_condition":?"((`ytt`.`t1`.`rank3`?=?100)?and?(`ytt`.`t1`.`rank2`?=?100)?and?(`ytt`.`t1`.`rank1`?=?100))"????}??}}1?row?in?set,?1?warning?(0.00?sec)

對比下以上兩個,加了HINT的比不加HINT的cost小了100倍。

總結(jié)下,就是說表的cardinality值影響這張的查詢計劃,如果這個值沒有正常更新的話,就需要手工加HINT了。相信MySQL未來的版本會帶來更多的HINT。

總結(jié)

以上是生活随笔為你收集整理的mysql 5.7 hint_新特性解读 | MySQL 8.0 新增 HINT 模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。