mysql高效查询_mysql 高效率查询背景
說起mysql查詢效率問題,就無法繞開索引問題,而innodb索引是mysql存儲引擎中的重中之重,innodb索引包括“主鍵索引(聚集索引)”也就是實際數據和主鍵數據存儲在一起的索引。innodb除了主鍵索引以外就是二級索引,二級索引葉子結點的數據區存儲的是主鍵,mysql每個數據頁面有16k大小,innodb在執行插入數據后就已經根據唯一鍵將數據頁排好順序,索引結構暫時不做過多解釋。
那我們新建二級索引的時可以根據“近1”原則創建,創建是參考sql語句:select ?COUNT(DISTINCT(CONCAT(date,name)))/count(*) ;
例如,想要建立兩個字段的聯合索引,而第二個字段你可以選擇使用前綴的創建方式,也就是第二個字段只使用部分數據。
比如查詢優化中我們要遵循最佳做前綴原則,這個時候我們很可能想根據后綴去查詢,我們可以將數據倒置后,存儲冗余一列在按照左匹配模糊查詢。
如網址列查詢我們可以存儲為:moc.udiab.www 這種形式。
按照創建索引涉及的列去重后的總數和數據總數做對比,結果越趨近于1,則索引查詢效果越好。因為越趨近于0說明數據差距不大,所掃描的數據代價越高。
=========JOIN=========
先說下join吧,兩個表的join操作,實質是將一張表的記錄放入另一張表進行匹配過濾,mysql有join_buffer_size設置,這個設置會決定每次從驅動表中拿出多少條數據去另一張表做過濾,如果內存允許的話,盡量將其調大(默認256KB)這樣會減少IO開銷,每次拿驅動表中多的數據去和另一張表的數據作匹配,sql優化器會試圖將兩個表的操作先優化為內連接也就是inner join,這樣做可以使用驅動表優化策略,會將小表設置為驅動表。
========子查詢========
子查詢的性能也是關鍵,子查詢可以分為相關子查詢和獨立子查詢;每種查詢方式又分為標量子查詢(返回單條記錄)和結果集子查詢。
(1)如:select * from td1 where name=(select a from td2 where td2.b=td1.c limit 1) ?相關子查詢中的標量子查詢;
其實相關標量子查詢,如果子查詢內能夠使用索引速度也是基本沒什么問題的,因為它會在外層查詢中先取出一條數據,然后去子查詢中做唯一匹配,雖然稍復雜些,但是性能損耗可以接受
(2)如:select * from td1 where name in (select a from td2) 獨立子查詢;
ps:如果是上面這種則相對復雜了很多,如果子查詢的返回結果數量沒有超過mysql服務的預設值(tmp_table_size),則會以memory引擎創建一個td2?臨時表并創建Hash索引,因為td1中是以等值方式去td2中匹配的;超過了就會創建磁盤物理表并建立B+Tree索引。
《2.1》針對于in子查詢,查詢優化器會將in優化為join,那么轉換為join的情況則不同,獨立子查詢如果子查詢返回數據庫唯一鍵,則直接可轉成join。
《2.2》如果子查詢返回非唯一鍵,則會使用物化表(按照ps的規則),將結果集先去重,然后在進行join。
(3)如:select * from td1 where name in (select a from td2 where td1.a=td2.b) 相關子查詢中使用了主鍵;
相關子查詢去重后在進行semi join,使用以下命令選擇開啟:
semijoin={on|off}
materialization={on|off}
loosescan={on|off}
subquery_materialization_cost_based={on|off}
4種情況:
《3.1》如果子查詢中select返回是數據庫唯一鍵 ,情況也是直接轉換為semi join。
《3.2》mysql會創建一個臨時表,每次將主表數據取出后在子查詢表中查找數據,查找到以后插入臨時表,該臨時表中不會有重復的數據,當數據插入完畢以后,在與臨時表做semi join。
《3.3》使用FirstMatch方法在子查詢表中返回一條語句后,即返回,不在向后繼續尋找。
《3.4》使用LooseScan,依賴本身的索引,進行group by進行去重后,在semi join
==================
mysql查詢部分包括,(1)sql執行器,(2)sql優化器。
sql優化的執行過程可以先開啟sql優化日志后(SET optimizer_trace='enabled=on';),到information_schema.OPTIMIZER_TRACE這個表中進行優化過程的查詢,結合查詢計劃就能夠看到mysql究竟是怎樣執行最終的sql的。
查詢優化日志中,我們可以主要觀察where條件優化,join優化,和analyzing_range_alternatives查詢成本優化。
這里我們可以拿analysisi_query_cost查詢成本優化為例,row查詢默認開銷因子為0.2,主鍵索引數據頁查詢因子為1,按照公式=主鍵索引數據頁*1+行數*0.2,最終獲得查詢成本cost的值,優化器會根據cost值,取最小的執行查詢。
{"steps": [
{"join_preparation": {"select#": 1,"steps": [
{"expanded_query": "/* select#1 */ select `t_day_stock`.`STOCK` AS `STOCK`,`t_day_stock`.`DATE` AS `DATE`,`t_day_stock`.`OPEN` AS `OPEN`,`t_day_stock`.`CLOSE` AS `CLOSE`,`t_day_stock`.`HIGH` AS `HIGH`,`t_day_stock`.`LOW` AS `LOW`,`t_day_stock`.`VOLUME` AS `VOLUME`,`t_day_stock`.`VALUE` AS `VALUE`,`t_day_stock`.`NUMBER_OF_TRADES` AS `NUMBER_OF_TRADES`,`t_day_stock`.`PRECLOSE` AS `PRECLOSE` from `t_day_stock` where ((`t_day_stock`.`STOCK` = '600228.SH') and (`t_day_stock`.`DATE` < '2004-01-12'))"}
]
}
},
{"join_optimization": {"select#": 1,"steps": [
{"condition_processing": {"condition": "WHERE","original_condition": "((`t_day_stock`.`STOCK` = '600228.SH') and (`t_day_stock`.`DATE` < '2004-01-12'))","steps": [
{"transformation": "equality_propagation","resulting_condition": "((`t_day_stock`.`STOCK` = '600228.SH') and (`t_day_stock`.`DATE` < '2004-01-12'))"},
{"transformation": "constant_propagation","resulting_condition": "((`t_day_stock`.`STOCK` = '600228.SH') and (`t_day_stock`.`DATE` < '2004-01-12'))"},
{"transformation": "trivial_condition_removal","resulting_condition": "((`t_day_stock`.`STOCK` = '600228.SH') and (`t_day_stock`.`DATE` < '2004-01-12'))"}
]
}
},
{"table_dependencies": [
{"table": "`t_day_stock`","row_may_be_null": false,"map_bit": 0,"depends_on_map_bits": [
]
}
]
},
{"ref_optimizer_key_uses": [
{"table": "`t_day_stock`","field": "STOCK","equals": "'600228.SH'","null_rejecting": false},
{"table": "`t_day_stock`","field": "STOCK","equals": "'600228.SH'","null_rejecting": false},
{"table": "`t_day_stock`","field": "STOCK","equals": "'600228.SH'","null_rejecting": false}
]
},
{"rows_estimation": [
{"table": "`t_day_stock`","range_analysis": {"table_scan": {"rows": 425496,"cost": 98608},"potential_range_indices": [
{"index": "PRIMARY","usable": true,"key_parts": ["STOCK","DATE"]
},
{"index": "stock_date","usable": true,"key_parts": ["STOCK","DATE"]
},
{"index": "stock","usable": true,"key_parts": ["STOCK"]
},
{"index": "date","usable": true,"key_parts": ["DATE"]
}
],"setup_range_conditions": [
],"group_index_range": {"chosen": false,"cause": "not_group_by_or_distinct"},"analyzing_range_alternatives": {"range_scan_alternatives": [
{"index": "PRIMARY","ranges": ["600228.SH <= STOCK <= 600228.SH AND DATE < 2004-01-12 00:00:00"],"index_dives_for_eq_ranges": true,"rowid_ordered": false,"using_mrr": false,"index_only": false,"rows": 3,"cost": 4.61,"chosen": true},
{"index": "stock_date","ranges": ["600228.SH <= STOCK <= 600228.SH AND DATE < 2004-01-12 00:00:00"],"index_dives_for_eq_ranges": true,"rowid_ordered": false,"using_mrr": false,"index_only": false,"rows": 5,"cost": 7.01,"chosen": false,"cause": "cost"},
{"index": "stock","ranges": ["600228.SH <= STOCK <= 600228.SH"],"index_dives_for_eq_ranges": true,"rowid_ordered": true,"using_mrr": false,"index_only": false,"rows": 468,"cost": 562.61,"chosen": false,"cause": "cost"},
{"index": "date","ranges": ["DATE < 2004-01-12 00:00:00"],"index_dives_for_eq_ranges": true,"rowid_ordered": false,"using_mrr": false,"index_only": false,"rows": 7450,"cost": 8941,"chosen": false,"cause": "cost"}
],"analyzing_roworder_intersect": {"usable": false,"cause": "too_few_roworder_scans"}
},"chosen_range_access_summary": {"range_access_plan": {"type": "range_scan","index": "PRIMARY","rows": 3,"ranges": ["600228.SH <= STOCK <= 600228.SH AND DATE < 2004-01-12 00:00:00"]
},"rows_for_plan": 3,"cost_for_plan": 4.61,"chosen": true}
}
}
]
},
{"considered_execution_plans": [
{"plan_prefix": [
],"table": "`t_day_stock`","best_access_path": {"considered_access_paths": [
{"access_type": "ref","index": "PRIMARY","rows": 4254,"cost": 5105.8,"chosen": true},
{"access_type": "ref","index": "stock_date","rows": 310,"cost": 372,"chosen": true},
{"access_type": "ref","index": "stock","rows": 468,"cost": 561.6,"chosen": false},
{"access_type": "range","rows": 3,"cost": 5.21,"chosen": true}
]
},"cost_for_plan": 5.21,"rows_for_plan": 3,"chosen": true}
]
},
{"attaching_conditions_to_tables": {"original_condition": "((`t_day_stock`.`STOCK` = '600228.SH') and (`t_day_stock`.`DATE` < '2004-01-12'))","attached_conditions_computation": [
],"attached_conditions_summary": [
{"table": "`t_day_stock`","attached": "((`t_day_stock`.`STOCK` = '600228.SH') and (`t_day_stock`.`DATE` < '2004-01-12'))"}
]
}
},
{"refine_plan": [
{"table": "`t_day_stock`","pushed_index_condition": "((`t_day_stock`.`STOCK` = '600228.SH') and (`t_day_stock`.`DATE` < '2004-01-12'))","table_condition_attached": null,"access_type": "range"}
]
}
]
}
},
{"join_explain": {"select#": 1,"steps": [
]
}
}
]
}
總結
以上是生活随笔為你收集整理的mysql高效查询_mysql 高效率查询背景的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 带你梳理一遍 Android 核心知识
- 下一篇: 指定服务器不存在或访问被拒绝访问,SQL