MSQY的查询计划(重点)

01、目标

了解查询优化器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hjxLR4OV-1629391403875)(查询计划.assets/image-20210723212750676.png)]

02、查询优化器

查询优化器的作用:就是根据你执行的SQL语句,进行分析,它自动的去通过他里面提供的算法和结构。进行对你的sql执行和预判。选择一个最优的方法,进行一个执行和处理。

能不能通过一些方式,来查看SQL在执行执行过程中到底是怎么确定的执行的顺序,和是否命中到了索引呢?

03:分析

查询优化器的任务是找到执行SQL查询的最佳计划,是MYSQL数据库的一个核心功能模块。
根据表、列、索引的详细信息以及SQL语句中的条件,很多方面来让SQL高效的执行。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DITGGYib-1629391403878)(查询计划.assets/kuangstudyd9bd04ec-bfd0-4327-a5c4-b2ff1cd2494b.png)]

04、执行计划原理分析

优化器选择执行效率最高的查询的一组操作称之为:查询执行计划,也称之为Explain计划。分析Explain计划可以发现一些导致SQL低下的原因

参考官网:https://dev.mysql.com/doc/internals/en/optimizer-tracing-typical-usage.html

比如有 一个SQL语句:

SELECT * FROM kss_user WHERE userid > 5 AND email='xuchengfeifei@163.com';

这条SQL语句在MYSQL内部的优化器中,到底是先执行userid还是先过滤email呢?

这个的话完全由MYSQL的优化器来决定。我们开发者不要理所当然的先执行userid在执行email。这是错误的认知

05、面向场景分析:重点:记住下来

面试场景1分析:select * from table where a = 1 and b = 2 and c= 3 问。a,b,c先执行谁?

如果你回答:a,b,c / b,c,a 可能都是错的也可能都是对的?飞哥不是很矛盾吗?

答案:你写的这个SQL语句,我不能直接告诉你的他们之间的执行顺序,必须要通过查询计划才能够确定他们的执行顺序。完全由MYSQL的优化器来决定。我们开发者不要理所当然的先执行a在执行b执行c。这是错误的认知

举个列子

SELECT * FROM kss_user WHERE userid > 5 AND email='xuchengfeifei@163.com';

开启sql执行的查询计划的分析

SET optimizer_trace="enabled=on";
SELECT * FROM kss_user WHERE userid > 5 AND email='xuchengfeifei@163.com';
SELECT * FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE;
SET optimizer_trace="enabled=off";

的到结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AjjXwh4A-1629391403881)(查询计划.assets/image-20210723214703107.png)]

{
  "steps": [
    {
      "join_preparation": {
        "select#": 1,
        "steps": [
          {
            "expanded_query": "/* select#1 */ select `kss_user`.`id` AS `id`,`kss_user`.`nickname` AS `nickname`,`kss_user`.`password` AS `password`,`kss_user`.`age` AS `age`,`kss_user`.`male` AS `male`,`kss_user`.`user_intro` AS `user_intro`,`kss_user`.`create_time` AS `create_time`,`kss_user`.`update_time` AS `update_time`,`kss_user`.`active` AS `active`,`kss_user`.`update_count` AS `update_count`,`kss_user`.`version` AS `version` from `kss_user` where ((`kss_user`.`id` > 5) and (`kss_user`.`nickname` = 'xuchengfeifei@163.com'))"
          }
        ]
      }
    },
    {
      "join_optimization": {
        "select#": 1,
        "steps": [
          {
            "condition_processing": {
              "condition": "WHERE",
              "original_condition": "((`kss_user`.`id` > 5) and (`kss_user`.`nickname` = 'xuchengfeifei@163.com'))",
              "steps": [
                {
                  "transformation": "equality_propagation",
                  "resulting_condition": "((`kss_user`.`id` > 5) and (`kss_user`.`nickname` = 'xuchengfeifei@163.com'))"
                },
                {
                  "transformation": "constant_propagation",
                  "resulting_condition": "((`kss_user`.`id` > 5) and (`kss_user`.`nickname` = 'xuchengfeifei@163.com'))"
                },
                {
                  "transformation": "trivial_condition_removal",
                  "resulting_condition": "((`kss_user`.`id` > 5) and (`kss_user`.`nickname` = 'xuchengfeifei@163.com'))"
                }
              ]
            }
          },
          {
            "substitute_generated_columns": {
            }
          },
          {
            "table_dependencies": [
              {
                "table": "`kss_user`",
                "row_may_be_null": false,
                "map_bit": 0,
                "depends_on_map_bits": [
                ]
              }
            ]
          },
          {
            "ref_optimizer_key_uses": [
              {
                "table": "`kss_user`",
                "field": "nickname",
                "equals": "'xuchengfeifei@163.com'",
                "null_rejecting": false
              }
            ]
          },
          {
            "rows_estimation": [
              {
                "table": "`kss_user`",
                "range_analysis": {
                  "table_scan": {
                    "rows": 36,
                    "cost": 10.3
                  },
                  "potential_range_indexes": [
                    {
                      "index": "PRIMARY",
                      "usable": true,
                      "key_parts": [
                        "id"
                      ]
                    },
                    {
                      "index": "nickname_age_male_index",
                      "usable": true,
                      "key_parts": [
                        "nickname",
                        "age",
                        "male",
                        "id"
                      ]
                    }
                  ],
                  "setup_range_conditions": [
                  ],
                  "group_index_range": {
                    "chosen": false,
                    "cause": "not_group_by_or_distinct"
                  },
                  "analyzing_range_alternatives": {
                    "range_scan_alternatives": [
                      {
                        "index": "PRIMARY",
                        "ranges": [
                          "5 < id"
                        ],
                        "index_dives_for_eq_ranges": true,
                        "rowid_ordered": true,
                        "using_mrr": false,
                        "index_only": false,
                        "rows": 31,
                        "cost": 7.2668,
                        "chosen": true
                      },
                      {
                        "index": "nickname_age_male_index",
                        "ranges": [
                          "xuchengfeifei@163.com <= nickname <= xuchengfeifei@163.com"
                        ],
                        "index_dives_for_eq_ranges": true,
                        "rowid_ordered": false,
                        "using_mrr": false,
                        "index_only": false,
                        "rows": 1,
                        "cost": 2.21,
                        "chosen": true
                      }
                    ],
                    "analyzing_roworder_intersect": {
                      "usable": false,
                      "cause": "too_few_roworder_scans"
                    }
                  },
                  "chosen_range_access_summary": {
                    "range_access_plan": {
                      "type": "range_scan",
                      "index": "nickname_age_male_index",
                      "rows": 1,
                      "ranges": [
                        "xuchengfeifei@163.com <= nickname <= xuchengfeifei@163.com"
                      ]
                    },
                    "rows_for_plan": 1,
                    "cost_for_plan": 2.21,
                    "chosen": true
                  }
                }
              }
            ]
          },
          {
            "considered_execution_plans": [
              {
                "plan_prefix": [
                ],
                "table": "`kss_user`",
                "best_access_path": {
                  "considered_access_paths": [
                    {
                      "access_type": "ref",
                      "index": "nickname_age_male_index",
                      "rows": 1,
                      "cost": 1.2,
                      "chosen": true
                    },
                    {
                      "access_type": "range",
                      "range_details": {
                        "used_index": "nickname_age_male_index"
                      },
                      "chosen": false,
                      "cause": "heuristic_index_cheaper"
                    }
                  ]
                },
                "condition_filtering_pct": 100,
                "rows_for_plan": 1,
                "cost_for_plan": 1.2,
                "chosen": true
              }
            ]
          },
          {
            "attaching_conditions_to_tables": {
              "original_condition": "((`kss_user`.`id` > 5) and (`kss_user`.`nickname` = 'xuchengfeifei@163.com'))",
              "attached_conditions_computation": [
              ],
              "attached_conditions_summary": [
                {
                  "table": "`kss_user`",
                  "attached": "(`kss_user`.`id` > 5)"
                }
              ]
            }
          },
          {
            "refine_plan": [
              {
                "table": "`kss_user`",
                "pushed_index_condition": "(`kss_user`.`id` > 5)",
                "table_condition_attached": null
              }
            ]
          }
        ]
      }
    },
    {
      "join_execution": {
        "select#": 1,
        "steps": [
        ]
      }
    }
  ]
}

面试题场景2分析:SELECT * from employee e,department d,customer c where e.dep_id = d.id and e.cus_id = c.id;

如果你回答:e,d,c /d,c,e 可能都是错的也可能都是对的?飞哥不是很矛盾吗?

答案:你写的这个SQL语句,我不能直接告诉你的他们之间的执行顺序,必须要通过查询计划或者执行Expain执行分析才能够确定他们的执行顺序。完全由MYSQL的优化器来决定。我们开发者不要理所当然的先执行e在执行d执行c。这是错误的认知

{
  "steps": [
    {
      "join_preparation": {
        "select#": 1,
        "steps": [
          {
            "expanded_query": "/* select#1 */ select `a`.`id` AS `id`,`a`.`name` AS `name`,`a`.`dep_id` AS `dep_id`,`a`.`age` AS `age`,`a`.`salary` AS `salary`,`a`.`cus_id` AS `cus_id`,`b`.`id` AS `id`,`b`.`deptName` AS `deptName`,`b`.`address` AS `address`,`c`.`id` AS `id`,`c`.`name` AS `name` from `employee` `a` join `department` `b` join `customer` `c` where ((`a`.`dep_id` = `b`.`id`) and (`a`.`cus_id` = `c`.`id`))"
          }
        ]
      }
    },
    {
      "join_optimization": {
        "select#": 1,
        "steps": [
          {
            "condition_processing": {
              "condition": "WHERE",
              "original_condition": "((`a`.`dep_id` = `b`.`id`) and (`a`.`cus_id` = `c`.`id`))",
              "steps": [
                {
                  "transformation": "equality_propagation",
                  "resulting_condition": "(multiple equal(`a`.`dep_id`, `b`.`id`) and multiple equal(`a`.`cus_id`, `c`.`id`))"
                },
                {
                  "transformation": "constant_propagation",
                  "resulting_condition": "(multiple equal(`a`.`dep_id`, `b`.`id`) and multiple equal(`a`.`cus_id`, `c`.`id`))"
                },
                {
                  "transformation": "trivial_condition_removal",
                  "resulting_condition": "(multiple equal(`a`.`dep_id`, `b`.`id`) and multiple equal(`a`.`cus_id`, `c`.`id`))"
                }
              ]
            }
          },
          {
            "substitute_generated_columns": {
            }
          },
          {
            "table_dependencies": [
              {
                "table": "`employee` `a`",
                "row_may_be_null": false,
                "map_bit": 0,
                "depends_on_map_bits": [
                ]
              },
              {
                "table": "`department` `b`",
                "row_may_be_null": false,
                "map_bit": 1,
                "depends_on_map_bits": [
                ]
              },
              {
                "table": "`customer` `c`",
                "row_may_be_null": false,
                "map_bit": 2,
                "depends_on_map_bits": [
                ]
              }
            ]
          },
          {
            "ref_optimizer_key_uses": [
              {
                "table": "`department` `b`",
                "field": "id",
                "equals": "`a`.`dep_id`",
                "null_rejecting": true
              },
              {
                "table": "`customer` `c`",
                "field": "id",
                "equals": "`a`.`cus_id`",
                "null_rejecting": true
              }
            ]
          },
          {
            "rows_estimation": [
              {
                "table": "`employee` `a`",
                "table_scan": {
                  "rows": 8,
                  "cost": 1
                }
              },
              {
                "table": "`department` `b`",
                "table_scan": {
                  "rows": 5,
                  "cost": 1
                }
              },
              {
                "table": "`customer` `c`",
                "table_scan": {
                  "rows": 1,
                  "cost": 1
                }
              }
            ]
          },
          {
            "considered_execution_plans": [
              {
                "plan_prefix": [
                ],
                "table": "`employee` `a`",
                "best_access_path": {
                  "considered_access_paths": [
                    {
                      "rows_to_scan": 8,
                      "access_type": "scan",
                      "resulting_rows": 8,
                      "cost": 2.6,
                      "chosen": true
                    }
                  ]
                },
                "condition_filtering_pct": 100,
                "rows_for_plan": 8,
                "cost_for_plan": 2.6,
                "rest_of_plan": [
                  {
                    "plan_prefix": [
                      "`employee` `a`"
                    ],
                    "table": "`customer` `c`",
                    "best_access_path": {
                      "considered_access_paths": [
                        {
                          "access_type": "eq_ref",
                          "index": "PRIMARY",
                          "rows": 1,
                          "cost": 9.6,
                          "chosen": true,
                          "cause": "clustered_pk_chosen_by_heuristics"
                        },
                        {
                          "rows_to_scan": 1,
                          "access_type": "scan",
                          "using_join_cache": true,
                          "buffers_needed": 1,
                          "resulting_rows": 1,
                          "cost": 2.6025,
                          "chosen": true
                        }
                      ]
                    },
                    "condition_filtering_pct": 100,
                    "rows_for_plan": 8,
                    "cost_for_plan": 5.2025,
                    "rest_of_plan": [
                      {
                        "plan_prefix": [
                          "`employee` `a`",
                          "`customer` `c`"
                        ],
                        "table": "`department` `b`",
                        "best_access_path": {
                          "considered_access_paths": [
                            {
                              "access_type": "eq_ref",
                              "index": "PRIMARY",
                              "rows": 1,
                              "cost": 9.6,
                              "chosen": true,
                              "cause": "clustered_pk_chosen_by_heuristics"
                            },
                            {
                              "rows_to_scan": 5,
                              "access_type": "scan",
                              "using_join_cache": true,
                              "buffers_needed": 1,
                              "resulting_rows": 5,
                              "cost": 9.0261,
                              "chosen": true
                            }
                          ]
                        },
                        "condition_filtering_pct": 100,
                        "rows_for_plan": 40,
                        "cost_for_plan": 14.229,
                        "chosen": true
                      }
                    ]
                  },
                  {
                    "plan_prefix": [
                      "`employee` `a`"
                    ],
                    "table": "`department` `b`",
                    "best_access_path": {
                      "considered_access_paths": [
                        {
                          "access_type": "eq_ref",
                          "index": "PRIMARY",
                          "rows": 1,
                          "cost": 9.6,
                          "chosen": true,
                          "cause": "clustered_pk_chosen_by_heuristics"
                        },
                        {
                          "rows_to_scan": 5,
                          "access_type": "scan",
                          "using_join_cache": true,
                          "buffers_needed": 1,
                          "resulting_rows": 5,
                          "cost": 9.0025,
                          "chosen": true
                        }
                      ]
                    },
                    "condition_filtering_pct": 20,
                    "rows_for_plan": 8,
                    "cost_for_plan": 11.603,
                    "pruned_by_heuristic": true
                  }
                ]
              },
              {
                "plan_prefix": [
                ],
                "table": "`customer` `c`",
                "best_access_path": {
                  "considered_access_paths": [
                    {
                      "access_type": "ref",
                      "index": "PRIMARY",
                      "usable": false,
                      "chosen": false
                    },
                    {
                      "rows_to_scan": 1,
                      "access_type": "scan",
                      "resulting_rows": 1,
                      "cost": 1.2,
                      "chosen": true
                    }
                  ]
                },
                "condition_filtering_pct": 100,
                "rows_for_plan": 1,
                "cost_for_plan": 1.2,
                "rest_of_plan": [
                  {
                    "plan_prefix": [
                      "`customer` `c`"
                    ],
                    "table": "`employee` `a`",
                    "best_access_path": {
                      "considered_access_paths": [
                        {
                          "rows_to_scan": 8,
                          "access_type": "scan",
                          "using_join_cache": true,
                          "buffers_needed": 1,
                          "resulting_rows": 8,
                          "cost": 2.6029,
                          "chosen": true
                        }
                      ]
                    },
                    "condition_filtering_pct": 12.5,
                    "rows_for_plan": 1,
                    "cost_for_plan": 3.8029,
                    "rest_of_plan": [
                      {
                        "plan_prefix": [
                          "`customer` `c`",
                          "`employee` `a`"
                        ],
                        "table": "`department` `b`",
                        "best_access_path": {
                          "considered_access_paths": [
                            {
                              "access_type": "eq_ref",
                              "index": "PRIMARY",
                              "rows": 1,
                              "cost": 1.2,
                              "chosen": true,
                              "cause": "clustered_pk_chosen_by_heuristics"
                            },
                            {
                              "access_type": "scan",
                              "cost": 2,
                              "rows": 5,
                              "chosen": false,
                              "cause": "cost"
                            }
                          ]
                        },
                        "condition_filtering_pct": 100,
                        "rows_for_plan": 1,
                        "cost_for_plan": 5.0029,
                        "chosen": true
                      }
                    ]
                  },
                  {
                    "plan_prefix": [
                      "`customer` `c`"
                    ],
                    "table": "`department` `b`",
                    "best_access_path": {
                      "considered_access_paths": [
                        {
                          "access_type": "ref",
                          "index": "PRIMARY",
                          "usable": false,
                          "chosen": false
                        },
                        {
                          "rows_to_scan": 5,
                          "access_type": "scan",
                          "using_join_cache": true,
                          "buffers_needed": 1,
                          "resulting_rows": 5,
                          "cost": 2.0029,
                          "chosen": true
                        }
                      ]
                    },
                    "condition_filtering_pct": 100,
                    "rows_for_plan": 5,
                    "cost_for_plan": 3.2029,
                    "rest_of_plan": [
                      {
                        "plan_prefix": [
                          "`customer` `c`",
                          "`department` `b`"
                        ],
                        "table": "`employee` `a`",
                        "best_access_path": {
                          "considered_access_paths": [
                            {
                              "rows_to_scan": 8,
                              "access_type": "scan",
                              "using_join_cache": true,
                              "buffers_needed": 1,
                              "resulting_rows": 8,
                              "cost": 9.0189,
                              "chosen": true
                            }
                          ]
                        },
                        "condition_filtering_pct": 100,
                        "rows_for_plan": 40,
                        "cost_for_plan": 12.222,
                        "pruned_by_cost": true
                      }
                    ]
                  }
                ]
              },
              {
                "plan_prefix": [
                ],
                "table": "`department` `b`",
                "best_access_path": {
                  "considered_access_paths": [
                    {
                      "access_type": "ref",
                      "index": "PRIMARY",
                      "usable": false,
                      "chosen": false
                    },
                    {
                      "rows_to_scan": 5,
                      "access_type": "scan",
                      "resulting_rows": 5,
                      "cost": 2,
                      "chosen": true
                    }
                  ]
                },
                "condition_filtering_pct": 100,
                "rows_for_plan": 5,
                "cost_for_plan": 2,
                "pruned_by_heuristic": true
              }
            ]
          },
          {
            "attaching_conditions_to_tables": {
              "original_condition": "((`a`.`cus_id` = `c`.`id`) and (`b`.`id` = `a`.`dep_id`))",
              "attached_conditions_computation": [
              ],
              "attached_conditions_summary": [
                {
                  "table": "`customer` `c`",
                  "attached": null
                },
                {
                  "table": "`employee` `a`",
                  "attached": "((`a`.`cus_id` = `c`.`id`) and (`a`.`dep_id` is not null))"
                },
                {
                  "table": "`department` `b`",
                  "attached": null
                }
              ]
            }
          },
          {
            "refine_plan": [
              {
                "table": "`customer` `c`"
              },
              {
                "table": "`employee` `a`",
                "unknown_key_1": {
                  "constant_condition_in_bnl": "(`a`.`dep_id` is not null)"
                }
              },
              {
                "table": "`department` `b`"
              }
            ]
          }
        ]
      }
    },
    {
      "join_execution": {
        "select#": 1,
        "steps": [
        ]
      }
    }
  ]
}

总结

  • 覆盖索引(记住)
  • 查询计划,就是告诉后续sql执行过程中的一个过程,json数据。
  • 执行计划 explain,只不过是把查询计划的日志进行具象化的分析的过程
  • 重点:以后在面试这种,多表查询现后顺序的时候,知道该回答了吗?
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值