久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

MySQL怎樣選擇合適的索引

125次閱讀
沒有評論

共計 9683 個字符,預計需要花費 25 分鐘才能閱讀完成。

自動寫代碼機器人,免費開通

這篇文章主要介紹了 MySQL 怎樣選擇合適的索引,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓丸趣 TV 小編帶著大家一起了解一下。

先來看一個栗子

EXPLAIN select * from employees where name    a

MySQL 怎樣選擇合適的索引

如果用 name 索引查找數據需要遍歷 name 字段聯合索引樹,然后根據遍歷出來的主鍵值去主鍵索引樹里再去查出最終數據,成本比全表掃描還高。

可以用覆蓋索引優(yōu)化,這樣只需要遍歷 name 字段的聯合索引樹就可以拿到所有的結果。

EXPLAIN select name,age,position from employees where name    a

MySQL 怎樣選擇合適的索引

可以看到通過 select 出的字段是覆蓋索引,MySQL 底層使用了索引優(yōu)化。在看另一個 case:

EXPLAIN select * from employees where name    zzz

MySQL 怎樣選擇合適的索引

對于上面的這兩種 name a 和 name zzz 的執(zhí)行結果,mysql 最終是否選擇走索引或者一張表涉及多個索引,mysql 最終如何選擇索引,可以通過 trace 工具來一查究竟,開啟 trace 工具會影響 mysql 性能,所以只能臨時分析 sql 使用,用完之后需要立即關閉。

SET SESSION optimizer_trace= enabled=on ,end_markers_in_json=on; -- 開啟 trace
SELECT * FROM employees WHERE name    a  ORDER BY position;
SELECT * FROM information_schema.OPTIMIZER_TRACE;

看 trace 字段:

{
  steps : [
 {
  join_preparation : { -- 第一階段:SQl 準備階段
  select# : 1,
  steps : [
 {  expanded_query :  /* select#1 */ select `employees`.`id` AS `id`,`employees`.`name` AS `name`,`employees`.`age` AS `age`,`employees`.`position` AS `position`,`employees`.`hire_time` AS `hire_time` from `employees` where (`employees`.`name`    a) order by `employees`.`position` 
 }
 ] /* steps */
 } /* join_preparation */
 },
 {
  join_optimization : { -- 第二階段:SQL 優(yōu)化階段
  select# : 1,
  steps : [
 {
  condition_processing : { -- 條件處理
  condition :  WHERE ,
  original_condition :  (`employees`.`name`    a) ,
  steps : [
 {
  transformation :  equality_propagation ,
  resulting_condition :  (`employees`.`name`    a) 
 },
 {
  transformation :  constant_propagation ,
  resulting_condition :  (`employees`.`name`    a) 
 },
 {
  transformation :  trivial_condition_removal ,
  resulting_condition :  (`employees`.`name`    a) 
 }
 ] /* steps */
 } /* condition_processing */
 },
 {
  table_dependencies : [ -- 表依賴詳情
 {
  table :  `employees` ,
  row_may_be_null : false,
  map_bit : 0,
  depends_on_map_bits : [ ] /* depends_on_map_bits */
 }
 ] /* table_dependencies */
 },
 {
  ref_optimizer_key_uses : [ ] /* ref_optimizer_key_uses */
 },
 {
  rows_estimation : [ -- 預估標的訪問成本
 {
  table :  `employees` ,
  range_analysis : {
  table_scan : { -- 全表掃描情況
  rows : 3, -- 掃描行數
  cost : 3.7 -- 查詢成本
 } /* table_scan */,
  potential_range_indices : [ -- 查詢可能使用的索引
 {
  index :  PRIMARY , -- 主鍵索引
  usable : false,
  cause :  not_applicable 
 },
 {
  index :  idx_name_age_position , -- 輔助索引
  usable : true,
  key_parts : [
  name ,
  age ,
  position ,
  id 
 ] /* key_parts */
 },
 {
  index :  idx_age ,
  usable : false,
  cause :  not_applicable 
 }
 ] /* potential_range_indices */,
  setup_range_conditions : [ ] /* setup_range_conditions */,
  group_index_range : {
  chosen : false,
  cause :  not_group_by_or_distinct 
 } /* group_index_range */,
  analyzing_range_alternatives : { ‐‐分析各個索引使用成本
  range_scan_alternatives : [
 {
  index :  idx_name_age_position ,
  ranges : [
  a   name 
 ] /* ranges */,
  index_dives_for_eq_ranges : true,
  rowid_ordered : false,
  using_mrr : false,
  index_only : false, ‐‐是否使用覆蓋索引
  rows : 3, --‐‐索引掃描行數
  cost : 4.61, -- 索引使用成本
  chosen : false, ‐‐是否選擇該索引
  cause :  cost 
 }
 ] /* range_scan_alternatives */,
  analyzing_roworder_intersect : {
  usable : false,
  cause :  too_few_roworder_scans 
 } /* analyzing_roworder_intersect */
 } /* analyzing_range_alternatives */
 } /* range_analysis */
 }
 ] /* rows_estimation */
 },
 {
  considered_execution_plans : [
 {
  plan_prefix : [ ] /* plan_prefix */,
  table :  `employees` ,
  best_access_path : {
  considered_access_paths : [
 {
  access_type :  scan ,
  rows : 3,
  cost : 1.6,
  chosen : true,
  use_tmp_table : true
 }
 ] /* considered_access_paths */
 } /* best_access_path */,
  cost_for_plan : 1.6,
  rows_for_plan : 3,
  sort_cost : 3,
  new_cost_for_plan : 4.6,
  chosen : true
 }
 ] /* considered_execution_plans */
 },
 {
  attaching_conditions_to_tables : {  original_condition :  (`employees`.`name`    a) ,
  attached_conditions_computation : [ ] /* attached_conditions_computation */,
  attached_conditions_summary : [
 {
  table :  `employees` ,
  attached :  (`employees`.`name`    a) 
 }
 ] /* attached_conditions_summary */
 } /* attaching_conditions_to_tables */
 },
 {
  clause_processing : {
  clause :  ORDER BY ,
  original_clause :  `employees`.`position` ,
  items : [
 {
  item :  `employees`.`position` 
 }
 ] /* items */,
  resulting_clause_is_simple : true,
  resulting_clause :  `employees`.`position` 
 } /* clause_processing */
 },
 {
  refine_plan : [
 {
  table :  `employees` ,
  access_type :  table_scan 
 }
 ] /* refine_plan */
 },
 {
  reconsidering_access_paths_for_index_ordering : {
  clause :  ORDER BY ,
  index_order_summary : {
  table :  `employees` ,
  index_provides_order : false,
  order_direction :  undefined ,
  index :  unknown ,
  plan_changed : false
 } /* index_order_summary */
 } /* reconsidering_access_paths_for_index_ordering */
 }
 ] /* steps */
 } /* join_optimization */
 },
 {
  join_execution : { -- 第三階段:SQL 執(zhí)行階段
  select# : 1,
  steps : [
 {
  filesort_information : [
 {
  direction :  asc ,
  table :  `employees` ,
  field :  position 
 }
 ] /* filesort_information */,
  filesort_priority_queue_optimization : {
  usable : false,
  cause :  not applicable (no LIMIT) 
 } /* filesort_priority_queue_optimization */,
  filesort_execution : [ ] /* filesort_execution */,
  filesort_summary : {
  rows : 3,
  examined_rows : 3,
  number_of_tmp_files : 0,
  sort_buffer_size : 200704,
  sort_mode :  sort_key, additional_fields 
 } /* filesort_summary */
 }
 ] /* steps */
 } /* join_execution */
 }
 ] /* steps */
}

全表掃描的成本低于索引掃描,索引 MySQL 最終會選擇全表掃描。

SELECT * FROM employees WHERE name    zzz  ORDER BY position;
SELECT * FROM information_schema.OPTIMIZER_TRACE;
  steps : [
 {
  join_preparation : {
  select# : 1,
  steps : [
 {  expanded_query :  /* select#1 */ select `employees`.`id` AS `id`,`employees`.`name` AS `name`,`employees`.`age` AS `age`,`employees`.`position` AS `position`,`employees`.`hire_time` AS `hire_time` from `employees` where (`employees`.`name`    zzz) order by `employees`.`position` 
 }
 ] /* steps */
 } /* join_preparation */
 },
 {
  join_optimization : {
  select# : 1,
  steps : [
 {
  condition_processing : {
  condition :  WHERE ,
  original_condition :  (`employees`.`name`    zzz) ,
  steps : [
 {
  transformation :  equality_propagation ,
  resulting_condition :  (`employees`.`name`    zzz) 
 },
 {
  transformation :  constant_propagation ,
  resulting_condition :  (`employees`.`name`    zzz) 
 },
 {
  transformation :  trivial_condition_removal ,
  resulting_condition :  (`employees`.`name`    zzz) 
 }
 ] /* steps */
 } /* condition_processing */
 },
 {
  table_dependencies : [
 {
  table :  `employees` ,
  row_may_be_null : false,
  map_bit : 0,
  depends_on_map_bits : [ ] /* depends_on_map_bits */
 }
 ] /* table_dependencies */
 },
 {
  ref_optimizer_key_uses : [ ] /* ref_optimizer_key_uses */
 },
 {
  rows_estimation : [
 {
  table :  `employees` ,
  range_analysis : {
  table_scan : {
  rows : 3,
  cost : 3.7
 } /* table_scan */,
  potential_range_indices : [
 {
  index :  PRIMARY ,
  usable : false,
  cause :  not_applicable 
 },
 {
  index :  idx_name_age_position ,
  usable : true,
  key_parts : [
  name ,
  age ,
  position ,
  id 
 ] /* key_parts */
 },
 {
  index :  idx_age ,
  usable : false,
  cause :  not_applicable 
 }
 ] /* potential_range_indices */,
  setup_range_conditions : [ ] /* setup_range_conditions */,
  group_index_range : {
  chosen : false,
  cause :  not_group_by_or_distinct 
 } /* group_index_range */,
  analyzing_range_alternatives : {
  range_scan_alternatives : [
 {
  index :  idx_name_age_position ,
  ranges : [
  zzz   name 
 ] /* ranges */,
  index_dives_for_eq_ranges : true,
  rowid_ordered : false,
  using_mrr : false,
  index_only : false,
  rows : 1,
  cost : 2.21,
  chosen : true
 }
 ] /* range_scan_alternatives */,
  analyzing_roworder_intersect : {
  usable : false,
  cause :  too_few_roworder_scans 
 } /* analyzing_roworder_intersect */
 } /* analyzing_range_alternatives */,
  chosen_range_access_summary : {
  range_access_plan : {
  type :  range_scan ,
  index :  idx_name_age_position ,
  rows : 1,
  ranges : [
  zzz   name 
 ] /* ranges */
 } /* range_access_plan */,
  rows_for_plan : 1,
  cost_for_plan : 2.21,
  chosen : true
 } /* chosen_range_access_summary */
 } /* range_analysis */
 }
 ] /* rows_estimation */
 },
 {
  considered_execution_plans : [
 {
  plan_prefix : [ ] /* plan_prefix */,
  table :  `employees` ,
  best_access_path : {
  considered_access_paths : [
 {
  access_type :  range ,
  rows : 1,
  cost : 2.41,
  chosen : true,
  use_tmp_table : true
 }
 ] /* considered_access_paths */
 } /* best_access_path */,
  cost_for_plan : 2.41,
  rows_for_plan : 1,
  sort_cost : 1,
  new_cost_for_plan : 3.41,
  chosen : true
 }
 ] /* considered_execution_plans */
 },
 {
  attaching_conditions_to_tables : {  original_condition :  (`employees`.`name`    zzz) ,
  attached_conditions_computation : [ ] /* attached_conditions_computation */,
  attached_conditions_summary : [
 {
  table :  `employees` ,
  attached :  (`employees`.`name`    zzz) 
 }
 ] /* attached_conditions_summary */
 } /* attaching_conditions_to_tables */
 },
 {
  clause_processing : {
  clause :  ORDER BY ,
  original_clause :  `employees`.`position` ,
  items : [
 {
  item :  `employees`.`position` 
 }
 ] /* items */,
  resulting_clause_is_simple : true,
  resulting_clause :  `employees`.`position` 
 } /* clause_processing */
 },
 {
  refine_plan : [
 {
  table :  `employees` ,
  pushed_index_condition :  (`employees`.`name`    zzz) ,
  table_condition_attached : null,
  access_type :  range 
 }
 ] /* refine_plan */
 },
 {
  reconsidering_access_paths_for_index_ordering : {
  clause :  ORDER BY ,
  index_order_summary : {
  table :  `employees` ,
  index_provides_order : false,
  order_direction :  undefined ,
  index :  idx_name_age_position ,
  plan_changed : false
 } /* index_order_summary */
 } /* reconsidering_access_paths_for_index_ordering */
 }
 ] /* steps */
 } /* join_optimization */
 },
 {
  join_execution : {
  select# : 1,
  steps : [
 {
  filesort_information : [
 {
  direction :  asc ,
  table :  `employees` ,
  field :  position 
 }
 ] /* filesort_information */,
  filesort_priority_queue_optimization : {
  usable : false,
  cause :  not applicable (no LIMIT) 
 } /* filesort_priority_queue_optimization */,
  filesort_execution : [ ] /* filesort_execution */,
  filesort_summary : {
  rows : 0,
  examined_rows : 0,
  number_of_tmp_files : 0,
  sort_buffer_size : 200704,
  sort_mode :  sort_key, additional_fields 
 } /* filesort_summary */
 }
 ] /* steps */
 } /* join_execution */
 }
 ] /* steps */
}

查看 trace 字段可知索引掃描的成本低于全表掃描的成本,所以 MySQL 最終選擇索引掃描。

SET SESSION optimizer_trace= enabled=off  --  關閉 tra

感謝你能夠認真閱讀完這篇文章,希望丸趣 TV 小編分享的“MySQL 怎樣選擇合適的索引”這篇文章對大家有幫助,同時也希望大家多多支持丸趣 TV,關注丸趣 TV 行業(yè)資訊頻道,更多相關知識等著你來學習!

向 AI 問一下細節(jié)

正文完
 
丸趣
版權聲明:本站原創(chuàng)文章,由 丸趣 2023-12-04發(fā)表,共計9683字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發(fā)布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 营山县| 栖霞市| 湛江市| 察哈| 江阴市| 盐城市| 青冈县| 安国市| 偃师市| 西平县| 周口市| 鄂托克旗| 屏山县| 姜堰市| 称多县| 蕲春县| 镇雄县| 大新县| 深泽县| 南城县| 黄平县| 建平县| 广饶县| 商丘市| 龙里县| 聂荣县| 黑水县| 若尔盖县| 东乡族自治县| 通山县| 六安市| 分宜县| 泰宁县| 襄垣县| 木兰县| 新疆| 开化县| 兰西县| 金川县| 柳林县| 陇川县|