概念壹,數據的可選基數,也就是常說的基數值。
在生成各種執行計劃之前,查詢優化器必須從統計信息中獲取相關數據,從而估算出每個操作涉及的記錄數,這個相關數據就是基數。簡單來說就是每個字段中每個值的唯壹值分布狀態。
例如,表t1有100行記錄,其中壹行是f1。f1中唯壹值的個數可以是100,1,當然也可以是1到100之間的任意數。這裏唯壹的值是該列的可選基數。
那麽看到這壹點,我們就能理解為什麽需要在高基數的字段上建立索引,而低基數的沒有全表掃描快。當然這只是壹個方面,進壹步的討論不在我討論的範圍之內。
概念二,關於暗示的使用。
這裏我就說說什麽是暗示,什麽時候用暗示。
HINT簡單來說就是在壹些特定場景下,手動輔助MySQL優化器,讓她生成最優的執行計劃。壹般來說,優化器的執行計劃是最優的,但是在某些特定的場景中,執行計劃可能不是最優的。
比如表t1,經歷了很多頻繁的更新操作,(更新,刪除,插入),基數已經很不準確了。此時,壹條SQL剛剛被執行,因此這條SQL的執行計劃可能不是最優的。為什麽可能?
我們來看看具體的演示。
例如,下面兩個SQL,
答:
select * from t1其中f 1 = 20;
乙:
select * from t1其中f 1 = 30;
如果f1的值只是頻繁更新到30,並沒有達到MySQL自動更新基數值的臨界值,或者用戶設置了手動更新,或者用戶減少了樣本頁面等。,那麽這兩種說法可能都不準確。
順便提壹下,MySQL提供了自動更新和手動更新表的基數值的方法。由於篇幅有限,有需要可以參考手冊。
回到正題,MySQL 8.0帶來了幾個提示,所以我今天舉壹個index_merge的例子。
樣本表結構:
mysql & gtdesc t 1;+ - + - + - + - + - +|場?| Type | Null | Key | Default | Extra?|+-+--+-+-+| id | int(11)?|沒有?| PRI | NULL | auto _ increment | | rank 1?| int(11)?|是嗎?| MUL | NULL | || rank2?| int(11)?|是嗎?| MUL | NULL | || log_time?|日期時間|是?| MUL | NULL | | | prefix _ uid | varchar(100)|是?| | NULL | || desc1?|文|是?| | NULL | || rank3?| int(11)?|是嗎?| MUL | NULL | |+ - + - + - + - +集合中的7行(0.00秒)
表記錄的數量:
mysql & gt從t1中選擇count(*);+-+| count(*)|+-+| 32768 |+-+65438+集合中的0行(0.01秒)
這裏我們有兩個經典SQL:
SQL C:
select * from t1其中rank1 = 1或rank2 = 2或rank 3 = 2;
SQL D:
select * from t1其中rank1 =100?而rank2 =100?而rank 3 = 100;
表t1實際上有三個列的輔助索引:Rank1、Rank2和Rank3。
然後我們來看看SQL C的查詢計劃。
很明顯,沒有使用索引,掃描的行數是32034,開銷是3243.65。
mysql & gt解釋壹下?format=json select * from t1?其中rank1 =1或rank2 = 2或rank 3 = 2 \ G * * * * * * * * * * * * * * * * * * * * * 1。行* * * * * * * * * * * * * * * * * * * * * * * * * * *解釋:{?" query _ block ":{ " select _ id ":1," cost_info": {?" query_cost": "3243.65" }," table": {?" table_name": "t1 "," access_type": "ALL ",?" possible _ keys ":[" idx _ rank 1 "," idx_rank2 "," idx_rank3 "?], ?" rows_examined_per_scan": 32034,?" rows _ produced _ per _ join ":115,?「過濾」:「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 `.` t 1 `.` rank 1 `= 1 ` .)or(` ytt `.` t 1 `.` rank 3 ` = 2))" }?}}集合中的1行,1警告(0.00秒)
讓我們向同壹個查詢添加提示,並再次查看查詢計劃。
此時使用index_merge、union union,使用三列。掃描的行數是1103,花費是441.09,明顯比以前快了好幾倍。
mysql & gt解釋壹下?format = JSON select/*+index _ merge(t 1)*/* from t 1?其中rank1 =1或rank2 = 2或rank 3 = 2 \ G * * * * * * * * * * * * * * * * * * * * * 1。行* * * * * * * * * * * * * * * * * * * * * * * * * * *解釋:{?" query _ block ":{ " select _ id ":1," cost_info": {?" query_cost": "441.09" }," table": {?" table_name": "t1 "," access_type": "index_merge "," possible _ keys ":[" idx _ rank 1 "," 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,?“已過濾”:“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 `.` t 1 `.` rank 1 `= 1 ` .)or(` ytt `.` t 1 `.` rank 3 ` = 2))" }?}}集合中的1行,1警告(0.00秒)
讓我們再來看看SQL D的計劃:
沒有提示,
mysql & gtexplain format = JSON select * from t 1其中rank1 =100,rank2 =100,rank 3 = 100 \ G * * * * * * * * * * * * * * * * * * * * * 1。行* * * * * * * * * * * * * * * * * * * * * * * * * * *解釋:{?" query _ block ":{ " select _ id ":1," cost_info": {?" query_cost": "534.34" }," table": {?" table_name": "t1 "," access_type": "ref ",?" possible _ keys ":[" idx _ rank 1 "," 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,?“已過濾”:“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 `.` t 1 `.` rank 3 ` = 100)和(` ytt `.` t 1 `.` rank 2 ` = 100))" }?}}集合中的1行,1警告(0.00秒)
有了提示,
mysql & gtexplain format = JSON select/*+index _ merge(t 1)*/* from t 1其中rank1 =100,rank2 =100,rank 3 = 100 \ G * * * * * * * * * * * * * * * * * * * * * * * * * 1。行* * * * * * * * * * * * * * * * * * * * * * * * * * *解釋:{?" query _ block ":{ " select _ id ":1," cost_info": {?" query_cost": "5.23" }," table": {?" table_name": "t1 "," access_type": "index_merge "," possible _ keys ":[" idx _ rank 1 "," idx_rank2 "," idx_rank3 "?], ?" key ":" intersect(idx _ rank 1,idx_rank2,idx_rank3)",?" key_length": "5,5,5 "," rows _ examined _ per _ scan ":1,?" rows _ produced _ per _ join ":1,?“已過濾”:“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 `.` t 1 `.` rank 3 ` = 100)and(` ytt `.` t 1 `.` rank 1 `= 100))" }?}}集合中的1行,1警告(0.00秒)
對比以上兩者,有提示的代價比沒有提示的小100倍。
總而言之,表的基數值影響這個查詢計劃。如果該值沒有正常更新,則需要手動添加提示。相信未來的MySQL版本會帶來更多的提示。