MySQL的sql语句由客户端发出,经过连接和权限验证后,最终达到服务器端,由服务器分配thread线程处理,之后就是要介绍的具体服务器端的thread线程是怎么处理每条sql语句的。【 了解thread请看后续博客或官方、各大厂分享文档】。

1、SQL解析

2、SQL MySQL内部优化与执行

1、

MySQL解析完sql以后,会生成很多item类。item类是sql解析和执行中最重要的类之一。

【Filed介绍】
MYSQL中Filed有以下几种类型:
enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
MYSQL_TYPE_SHORT, MYSQL_TYPE_LONG,
MYSQL_TYPE_FLOAT, MYSQL_TYPE_DOUBLE,
MYSQL_TYPE_NULL, MYSQL_TYPE_TIMESTAMP,
MYSQL_TYPE_LONGLONG,MYSQL_TYPE_INT24,
MYSQL_TYPE_DATE, MYSQL_TYPE_TIME,
MYSQL_TYPE_DATETIME, MYSQL_TYPE_YEAR,
MYSQL_TYPE_NEWDATE,
MYSQL_TYPE_ENUM=247,
MYSQL_TYPE_SET=248,
MYSQL_TYPE_TINY_BLOB=249,
MYSQL_TYPE_MEDIUM_BLOB=250,
MYSQL_TYPE_LONG_BLOB=251,
MYSQL_TYPE_BLOB=252,
MYSQL_TYPE_VAR_STRING=253,
MYSQL_TYPE_STRING=254,
MYSQL_TYPE_GEOMETRY=255
};

  

【ITEM介绍】
在MYSQL中,有以下ITEM大类型:
FIELD_ITEM, FUNC_ITEM, SUM_FUNC_ITEM, STRING_ITEM, INT_ITEM, REAL_ITEM, NULL_ITEM, VARBIN_ITEM, COPY_STR_ITEM, FIELD_AVG_ITEM, DEFAULT_VALUE_ITEM,
PROC_ITEM,COND_ITEM, REF_ITEM, FIELD_STD_ITEM, FIELD_VARIANCE_ITEM, INSERT_VALUE_ITEM, SUBSELECT_ITEM, ROW_ITEM, CACHE_ITEM, TYPE_HOLDER, PARAM_ ITEM其中许多ITEM还有小类,如Item_func有如下小类型:
UNKNOWN_FUNC,EQ_FUNC,EQUAL_FUNC,NE_FUNC,LT_FUNC,LE_FUNC, GE_FUNC,GT_FUNC,FT_FUNC, LIKE_FUNC,NOTLIKE_FUNC,ISNULL_FUNC,ISNOTNULL_FUNC,
COND_AND_FUNC, COND_OR_FUNC, COND_XOR_FUNC, BETWEEN, IN_FUNC, INTERVAL_FUNC, ISNOTNULLTEST_FUNC, SP_EQUALS_FUNC, SP_DISJOINT_FUNC,
SP_INTERSECTS_FUNC, SP_TOUCHES_FUNC,SP_CROSSES_FUNC,SP_WITHIN_FUNC, SP_CONTAINS_FUNC,SP_OVERLAPS_FUNC, SP_STARTPOINT,SP_ENDPOINT,SP_EXTERIORRING,
SP_POINTN,SP_GEOMETRYN,SP_INTERIORRINGN, NOT_FUNC, NOT_ALL_FUNC, NOW_FUNC, VAR_VALUE_FUNC
 【FIELD和ITEM的关系】
通过Item类中的tmp_table_field_from_field_type函数将一个Item类转化为一个Filed类返回。并不是所有的Item类返回的Filed都有意义,下面列举几个有意义的转化:
Item_int ->Field_longlong
Item_real->Field_double
Item_string->Field_string

  

【解析结果存放实例】
例如语句select table1.field1,'test',100 from table1 where table1.field1='field1' and (table1.field2=100 or table1.field2=200)
1) 选择域的解析——“table1.field1,'test',100”
将被解析为一个List<Item>
其中List的第一个元素Item的子类Item_field,表示表中的列。
第二个元素为Item_string,表示字符串。由val_str方法可获得string值”test”,也可用tmp_table_field_from_field_type方法返回一个Field的子类Field_string的指针。
第三个元素为Item_int,表示整数。由val_int获得int值100,也可以用tmp_table_field_from_field_type方法返回一个Field的子类Field_longlong的指针。
2) Where域的解析——where table1.field1='field1' and (table1.field2=100 or table1.field2=200)
将被解析为一个Item对象,这个对象有个层次结构。
【对各类型SQL语句的解析】
MYSQL的语句类型有如下类型:
enum enum_sql_command {
SQLCOM_SELECT, SQLCOM_CREATE_TABLE, SQLCOM_CREATE_INDEX, SQLCOM_ALTER_TABLE,
SQLCOM_UPDATE, SQLCOM_INSERT, SQLCOM_INSERT_SELECT,
SQLCOM_DELETE, SQLCOM_TRUNCATE, SQLCOM_DROP_TABLE, SQLCOM_DROP_INDEX,
SQLCOM_SHOW_DATABASES, SQLCOM_SHOW_TABLES, SQLCOM_SHOW_FIELDS,
SQLCOM_SHOW_KEYS, SQLCOM_SHOW_VARIABLES, SQLCOM_SHOW_LOGS, SQLCOM_SHOW_STATUS,
SQLCOM_SHOW_INNODB_STATUS,SQLCOM_SHOW_NDBCLUSTER_STATUS,
SQLCOM_SHOW_PROCESSLIST, SQLCOM_SHOW_MASTER_STAT, SQLCOM_SHOW_SLAVE_STAT,
SQLCOM_SHOW_GRANTS, SQLCOM_SHOW_CREATE, SQLCOM_SHOW_CHARSETS,
SQLCOM_SHOW_COLLATIONS, SQLCOM_SHOW_CREATE_DB,
SQLCOM_LOAD,SQLCOM_SET_OPTION,SQLCOM_LOCK_TABLES,SQLCOM_UNLOCK_TABLES,
SQLCOM_GRANT,
SQLCOM_CHANGE_DB, SQLCOM_CREATE_DB, SQLCOM_DROP_DB, SQLCOM_ALTER_DB,
SQLCOM_REPAIR, SQLCOM_REPLACE, SQLCOM_REPLACE_SELECT,
SQLCOM_CREATE_FUNCTION, SQLCOM_DROP_FUNCTION,
SQLCOM_REVOKE,SQLCOM_OPTIMIZE, SQLCOM_CHECK,
SQLCOM_ASSIGN_TO_KEYCACHE, SQLCOM_PRELOAD_KEYS,
SQLCOM_FLUSH, SQLCOM_KILL, SQLCOM_ANALYZE,
SQLCOM_ROLLBACK, SQLCOM_ROLLBACK_TO_SAVEPOINT,
SQLCOM_COMMIT, SQLCOM_SAVEPOINT,
SQLCOM_SLAVE_START, SQLCOM_SLAVE_STOP,
SQLCOM_BEGIN, SQLCOM_LOAD_MASTER_TABLE, SQLCOM_CHANGE_MASTER,
SQLCOM_RENAME_TABLE, SQLCOM_BACKUP_TABLE, SQLCOM_RESTORE_TABLE,
SQLCOM_RESET, SQLCOM_PURGE, SQLCOM_PURGE_BEFORE, SQLCOM_SHOW_BINLOGS,
SQLCOM_SHOW_OPEN_TABLES, SQLCOM_LOAD_MASTER_DATA,
SQLCOM_HA_OPEN, SQLCOM_HA_CLOSE, SQLCOM_HA_READ,
SQLCOM_SHOW_SLAVE_HOSTS, SQLCOM_DELETE_MULTI, SQLCOM_UPDATE_MULTI,
SQLCOM_SHOW_BINLOG_EVENTS, SQLCOM_SHOW_NEW_MASTER, SQLCOM_DO,
SQLCOM_SHOW_WARNS, SQLCOM_EMPTY_QUERY, SQLCOM_SHOW_ERRORS,
SQLCOM_SHOW_COLUMN_TYPES, SQLCOM_SHOW_STORAGE_ENGINES, SQLCOM_SHOW_PRIVILEGES,
SQLCOM_HELP, SQLCOM_DROP_USER, SQLCOM_REVOKE_ALL, SQLCOM_CHECKSUM,
SQLCOM_PREPARE, SQLCOM_EXECUTE, SQLCOM_DEALLOCATE_PREPARE,
SQLCOM_END
};
下文只对常用的select(SQLCOM_SELECT), update(SQLCOM_UPDATE), insert(SQLCOM_INSERT), delete(SQLCOM_DELETE)做一下介绍。
Select语句
对select类型的语句解析后,将结果存放在SELECT_LEX类中
其中:
选择域存放在SELECT_LEX::item_list中,类型为LIST<Item>
where域存放在SELECT_LEX::wheret中,类型为Item*
having域存放在SELECT_LEX::having中,类型为Item*
order域存放在SELECT_LEX::order_list中,实际类型为ORDER*
group域存放在SELECT_LEX::group_list中,实际类型为ORDER*
limit域存放在SELECT_LEX::select_limit中,unsigned long
table名字域存放在SELECT_LEX::table_list中,实际类型为TABLE_LIST*

Update语句
对update类型的语句解析后,将结果存放在SELECT_LEX类和LEX类中
其中:
更新域存放在SELECT_LEX::item_list中,类型为LIST<Item>
值域存放在LEX::value_list中,类型为LIST<Item>
where域存放在SELECT_LEX::wheret中,类型为Item*
table名字域存放在SELECT_LEX::table_list中,实际类型为TABLE_LIST*
(其中更新域和值域的结构请见上文中的4(1),where域的解构请见上文中的4(2), table名字域的解构类似于链表)

Insert语句
对insert类型的语句解析后,将结果存放在SELECT_LEX类和LEX类中
其中:
插入域存放在LEX::item_list中,类型为LIST<Item>
值域存放在LEX::many_values中,类型为LIST<LIST<Item>>
table名字域存放在SELECT_LEX::table_list中,实际类型为TABLE_LIST*
(其中插入域的结构请见上文中的4(1), 值域可以含有多个LIST<Item>, table名字域的解构类似于链表)
Delete语句
对delete类型的语句解析后,将结果存放在SELECT_LEX类中
其中:
where域存放在SELECT_LEX::wheret中,类型为Item*
limit域存放在SELECT_LEX::select_limit中,unsigned long
table名字域存放在SELECT_LEX::table_list中,实际类型为TABLE_LIST*

  

【如何使用】
由于用到了mysql的源码,必须先下载到mysql的源码,编译mysql源码,然后将makefile中的MYSQL_SRC_PATH改为实际的mysql的源码位置,然后编译。
Thd结构体:
Thd{
boolean is_fatal_error
select_lex lex;//select_lex

}
Select_lex结构体:
select_lex{
table_list;//链着所有table的链表。
sql_command;//SQLCOM_SELECT、SQLCOM_DELETE、SQLCOM_INSERT、SQLCOM_UPDATE

}
所用到的文件:
其中parse_base.cpp是对mysql源码的一个简单的封装,test_parse.cpp中是需要编写修改的代码。重要的部分介绍:
// yyparse是用yacc对sql进行解析
if (!yyparse((void *)&thd) && ! thd.is_fatal_error){
if(thd.lex == NULL
|| thd.lex->select_lex.table_list.first == NULL)
{
cout<<"内部错误"<<endl;
iRet = -1;
}
else
{
//获取LEX和SELECT_LEX对象
LEX *lex= thd.lex;
SELECT_LEX *select_lex= &lex->select_lex; //打印table的名字
TABLE_LIST* tables= (TABLE_LIST*) select_lex->table_list.first;
if(tables != NULL)
{
cout<<"table name:"<<tables->real_name<<endl;
} enum_sql_command command_type;
command_type = lex->sql_command;
switch(command_type)
{
case SQLCOM_SELECT:
//选择
break;
case SQLCOM_DELETE:
//删除
break;
case SQLCOM_INSERT:
//插入
break;
case SQLCOM_UPDATE:
//更新
break;
default:
//其他
iRet = -1;
}
}

  

2、

    对sql进行优化处理。
【例如select语句的优化具体是在JOIN::optimise函数中完成。(MySQL针对select的处理是转换成JOIN操作处理的)】
select A.id, B.score from student A left join subject B on A.id=B.id where A.age > 10 and B.score > 60;
优化过程会将join的key也转换为一个where条件,经过处理后,上面的sql就有了3个where条件:
A.age > 10;
A.id = B.id;
B.score > 60; sql执行
例如select语句的执行具体是在JOIN::exec(MySQL是将任何select都转换为JOIN来处理的)。即JOIN::exec函数,首先会调用send_fields函数,将最终结果的信息返回,
然后调用do_select。在do_select函数中,通过调用sub_select函数来具体实现join功能。

  

二、SQL的生命周期的更多相关文章

  1. spring(二、bean生命周期、用到的设计模式、常用注解)

    spring(二.bean生命周期.用到的设计模式.常用注解) Spring作为当前Java最流行.最强大的轻量级框架,受到了程序员的热烈欢迎.准确的了解Spring Bean的生命周期是非常必要的. ...

  2. Expo大作战(二)--expo的生命周期,expo社区交流方式,expo学习必备资源,开发使用expo时关注的一些问题

    简要:本系列文章讲会对expo进行全面的介绍,本人从2017年6月份接触expo以来,对expo的研究断断续续,一路走来将近10个月,废话不多说,接下来你看到内容,讲全部来与官网 我猜去全部机翻+个人 ...

  3. SQL Cursor生命周期

      阅读导航 1 Cursor Step 1.1 Create cursor 1.2 Parse statement 1.3 descript and define 1.4 Bind variable ...

  4. vue学习笔记(二)vue的生命周期和钩子函数

    前言 通过上一章的学习,我们已经初步的了解了vue到底是什么东西,可以干什么,而这一篇博客主要介绍vue的生命周期和它常用的钩子函数,如果有学过java的园友可能有接触到在学习servlet的时候学过 ...

  5. 深入理解PHP内核(二)概览-PHP生命周期与Zend引擎

    本文参考自<深入理解PHP内核>,地址:https://github.com/reeze/tipi 本文链接:http://www.orlion.ml/232/ 1.SAPI接口 SAPI ...

  6. MyEclipse Spring 学习总结二 Bean的生命周期

    文件结构可以参考上一节 Bean的生命周期有方法有:init-method,destroy-method ApplicationContext.xml 文件配置如下: <?xml version ...

  7. Maven之(二)Maven生命周期

    我们在开发项目的时候,不断地在编译.测试.打包.部署等过程,maven的生命周期就是对所有构建过程抽象与统一,生命周期包含项目的清理.初始化.编译.测试.打包.集成测试.验证.部署.站点生成等几乎所有 ...

  8. Maven 学习总结 (二) 之 生命周期与插件

    五.生命周期与插件 1.Maven有三套独立的生命周期:clean.default和site. clean生命周期的目的是清理项目,default生命周期的目的是构建项目,site生命周期的目的是建立 ...

  9. spring深入学习(二)-----bean的生命周期、IOC容器bean装配

    bean的生命周期 1.实例化Bean对于BeanFactory容器,当客户向容器请求一个尚未初始化的bean时,或初始化bean的时候需要注入另一个尚未初始化的依赖时,容器就会调用createBea ...

  10. 一步一步掌握java的线程机制(二)----Thread的生命周期

    之前讲到Thread的创建,那是Thread生命周期的第一步,其后就是通过start()方法来启动Thread,它会执行一些内部的管理工作然后调用Thread的run()方法,此时该Thread就是a ...

随机推荐

  1. bzoj1503[NOI2004]郁闷的出纳员——Splay

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1503 好奇怪呀!为什么而TLE? 各种修改终于卡时过了.可是大家比我快多了呀?难道是因为自己 ...

  2. Spring注入方式及用到的注解

    注入方式: 把DAO实现类注入到service实现类中,把service的接口(注意不要是service的实现类)注入到action中,注 入时不要new 这个注入的类,因为spring会自动注入,如 ...

  3. php项目有负载,$_SERVER['HTTP_X_FORWARDED_FOR']函数在不同系统中获取到的值形式不一样,ios系统苹果手机只能获取到一个ip(113.87.214.xxx),而安卓手机获取到的是2个ip中间逗号隔开的形式(113.87.214.xxx , xxx.xxx.xxx.xxx)

    这次由于有个抽奖活动功能,苹果手机每次都抽奖失败,安卓手机每次都抽奖失败(5台ios手机,8台Android手机). 错误日志查看是因为,抽奖用户的ip记录进数据库时出错,之前都是拿到ip直接插入数据 ...

  4. erlang的lists笔记

    一般循环用在遍历列表的时候,erlang有lists模块直接支持遍历,不需要自己写尾递归遍历list lists:foreach 用来遍历列表,不保存结果,最后一次返回ok lists:map 遍历列 ...

  5. qt的webkit

    qt4里面,在pro文件添加 QT += webkit qt5里面,在pro文件添加 QT += webkit webkitwidgets 备注: webkit不支持静态编译

  6. 0基础自学php教程

    轻松搞定网页设计之html 一.HTML介绍 1. HTML概念 HTML(Hyper Text Markup Language),即超文本标记语言.是目前网络上应用最为广泛的语言,是构成网页文档的主 ...

  7. CF - A. Writing Code

    本博客参考自这里 不是我说,我就觉得这题题目贼鸡儿难懂 所以只能看看别的博客如何解释这题题目的意思咯. 有n个程序,这n个程序运作产生m行代码,但是每个程序产生的BUG总和不能超过b,给出每个程序产生 ...

  8. appium+python自动化30-list定位(find_elements)

    前言 有时候页面上没有id属性,并且其它的属性不唯一,平常用的比较多的是单数(element)的定位方法,遇到元素属性不唯一,就无法直接定位到了. 于是我们可以通过复数(elements)定位,先定位 ...

  9. Big Water Problem

    链接:https://www.nowcoder.com/acm/contest/77/B来源:牛客网 Big Water Problem 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ ...

  10. click 模块使用方法说明

    !/usr/bin/env python -- coding: utf-8 -- import click @click.command() @click.option('--count', defa ...