MySQL查询优化器源码分析

本文旨在分析MySQL查询优化器的工作原理,通过源代码跟踪和调试,为开发人员和数据库管理员提供深入理解。文章从Parser阶段和Optimizer阶段展开,详细介绍了包括handle_select()、JOIN::prepare()、JOIN::optimize()等关键函数的调用流程和作用,揭示了MySQL如何制定查询执行计划并优化SQL。通过对MySQL 5.5.20版本的源码分析,帮助读者更好地理解和应用查询优化器。
摘要由CSDN通过智能技术生成


目的

基于之前出现的主从库分别执行相同语句,查询计划和执行时间不同的问题。通过对源代码跟踪和调试,对MySQL的查询优化器进行分析并编写文档,为开发人员和数据库管理人员提供查询SQL语句的建议。

 

基础

MySQL的设计架构在官方文档中给出,如下图所示。该图的具体描述和讲解,请参考官方文档或地址:http://dev.mysql.com/doc/refman/5.1/en/pluggable-storage-overview.html

 

图中Optimizer部分为本文研究的重点,主要对Parser解析之后的SQL,根据统计的数据,对访问代价进行权衡,制定执行计划。查询优化器是MySQL中比较活跃的一部分,代码会经常变动。但整体而言,对查询优化器整体把握和理解之后,其他的版本也基本可以轻松理解。以下内容将通过对MySQL 5.5.20版本的源码进行分析,供大家参考。

 

代码分析

1、Parser阶段

查询优化器相关的代码主要在sql/sql_select.cc文件中,而在执行该部分代码时,需要对之前的内容做简要说明。本文从Parser阶段case SQLCOM_SELECT:中调用execute_sqlcom_select()函数开始(参看源码sql/sql_parse.cc:2124行),该函数是实际的sql执行阶段,而sql真正执行需要按照一定的规则去执行。因此,需要先制定一个执行计划。但制定计划不能随便制定,需要有一定的依据。并且不能保证所有人写的SQL都是最优的,也就不能根据SQL就简单制定一个规则。于是,出现了SQL Optimizer,该部分不仅对SQL进行了优化,并且根据优化的结果制定查询的执行计划。最终根据执行计划执行,得到数据结果并返回。从代码看,execute_sqlcom_select()函数做了以上的所有工作。

以下将从execute_sqlcom_select()函数开始,逐层次的分析MySQL的查询优化是如何实现的。

2、Optimizer阶段

execute_sqlcom_select()函数中,调用了handle_select()函数,而该函数正是处理SQL查询的“入口函数”。

2.1 函数调用层次

首先,将主要的函数调用层次列出,函数层次以之前的“|”标示,以“>”标示进入函数,以“<”标示退出函数,红色标示为递归调用的函数,绿色和蓝色标示为互斥操作。

| | | | >handle_select

| | | | | >mysql_select/mysql_union

| | | | | | >JOIN::prepare

| | | | | | | >setup_tables

| | | | | | | <setup_tables

| | | | | | | >setup_fields

| | | | | | | <setup_fields

| | | | | | | >setup_without_group

| | | | | | | | >setup_conds

| | | | | | | | <setup_conds

| | | | | | | | >setup_order

| | | | | | | | <setup_order

| | | | | | | | >setup_group

| | | | | | | | <setup_group

| | | | | | | <setup_without_group

| | | | | | | >setup_procedure

| | | | | | | <setup_procedure

| | | | | | <JOIN::prepare

| | | | | | >JOIN::optimize

| | | | | | | >simplify_joins

| | | | | | | <simplify_joins

| | | | | | | >build_bitmap_for_nested_joins

| | | | | | | <build_bitmap_for_nested_joins

| | | | | | | >optimize_cond

| | | | | | | <optimize_cond

| | | | | | | >prune_partitions

| | | | | | | <prune_partitions

| | | | | | | >make_join_statistics

| | | | | | | | >make_select

| | | | | | | | <make_select

| | | | | | | | >get_quick_record_count

| | | | | | | | | >SQL_SELECT::test_quick_select

| | | | | | | | | | >get_mm_tree

| | | | | | | | | | <get_mm_tree

| | | | | | | | | | >get_best_group_min_max

| | | | | | | | | | <get_best_group_min_max

| | | | | | | | | | >get_key_scans_params

| | | | | | | | | | <get_key_scans_params

| | | | | | | | | | >get_best_ror_intersect

| | | | | | | | | | <get_best_ror_intersect

| | | | | | | | | | >get_best_disjunct_quick

| | | | | | | | | | <get_best_disjunct_quick

| | | | | | | | | | >TRP_RANGE::make_quick

| | | | | | | | | | <TRP_RANGE::make_quick

| | | | | | | | | <SQL_SELECT::test_quick_select

| | | | | | | | <get_quick_record_count

| | | | | | | | >choose_plan

| | | | | | | | | >optimize_straight_join

| | | | | | | | | | >best_access_path

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值