《Mysql应用Mysql - 性能优化之子查询》要点: 本文介绍了Mysql应用Mysql - 性能优化之子查询,希望对您有用。如果有疑问,可以联系我们。
导读:当Mysql Server的连接线程接收到Client发送过来的SQL请求后,会经过一系列的分解Parse,进行相应的分析,然后Mysql会通过查询优化器模...
MYSQL实例当Mysql Server的连接线程接收到Client发送过来的SQL请求后,然后Mysql会通过查询优化器模块,根据该Sql所涉及到的数据表的相关统计信息进行计算分析. 然后在得出一个Mysql自认为最合理最优化的数据访问方式,也就是我们常说的"执行计划",然后根据所得到的执行计划通过调用存储引擎接口来获取相应数据. 再对存储引擎返回的数据进行相关的处理,并一Client端所要求的格式作为结果集,返回给Client.
MYSQL实例注 : 这里所说的统计数据,是我们通过 Analyze table命令通知Mysql对表的相关数据作分析之后,所获取到的一些数据统计量. 这些数据对Mysql优化器而言是非常重要的,优化器所生成的执行计划的好坏,主要是由这些统计数据所决定的.
MYSQL实例1. 建表
?
- create?table?User(?
- Id?int?not?null?PRIMARY?key?auto_increment?,?
- NickName?varchar(50)?comment?'用户昵称',?
- Sex?int?comment?'性别',?
- Sign?varchar(50)?comment?'用户签名',?
- Birthday?datetime?comment?'用户生日',?
- CreateTime?datetime?comment?'创建时间'?
- )?default?charset=utf8?comment?'用户表';?
- ?
- create?table?UserGroup(?
- Id?int?not?null?PRIMARY?key?auto_increment?,?
- UserId?int?not?null?comment?'user?Id',?
- GroupId?int?not?null?comment?'用户组Id',?
- CreateTime?datetime?comment?'创建时间',?
- ?
- key?index_userid(groupid,?UserId)?using?btree?
- )?default?charset=utf8?comment?'用户组表';?
MYSQL实例2. 准备数据
?
- var?conStr?=?ConfigurationManager.ConnectionStrings["ConStr"].ToString();?
- using?(IDbConnection?conn?=?new?MySqlConnection(conStr))?
- {?
- ????Stopwatch?watch?=?new?Stopwatch();?
- ????var?sql?=?string.Empty;?
- ????var?names?=?new?string[]?{?"非",?"想",?"红",?"帝",?"德",?"看",?"梅",?"插",?"兔"?};?
- ????Random?ran?=?new?Random();???
- ????var?insertSql?=?@"?insert?into?User(NickName,Sex,Sign,?Birthday,?CreateTime)?values(@NickName,@Sex,@Sign,?@Birthday,?@CreateTime);??
- ????INSERT?INTO?usergroup??(UserId,??GroupId,??CreateTime?)??VALUES?(LAST_INSERT_ID()?,???@GroupId,??@CreateTime);";?
- ????watch.Start();?
- ????if?(conn.State?==?ConnectionState.Closed)?
- ????{?
- ????????conn.Open();?
- ????}?
- ?
- ????var?tran?=?conn.BeginTransaction();?
- ????for?(int?i?=?0;?i?<?100000;?i++)?
- ????{?
- ????????var?param?=?new?{?NickName?=?names[ran.Next(9)]?+?names[ran.Next(9)]?+?i,?Sign?=?names[ran.Next(9)]?+?names[ran.Next(9)],?CreateTime?=?DateTime.Now,?Birthday?=?DateTime.Now.AddYears(ran.Next(10,?30)),?Sex?=?i?%?2,?GroupId?=?ran.Next(1,?100)?};?
- ????????conn.Execute(insertSql,?param,?tran);?
- ????}?
- ????tran.Commit();?
- ?
- ????conn.Dispose();?
- ????watch.Stop();?
- ????Console.WriteLine(watch.ElapsedMilliseconds);?
- }?
MYSQL实例这里我插入了5000条数据,group分了99个组,随机的.?
MYSQL实例?
MYSQL实例3. 查询sql
?
- explain?
- select?user.id,?user.nickname?from?usergroup??
- left?join?user??on?usergroup.UserId?=?user.Id?
- where??usergroup.groupid?=?1??
- order?by?usergroup.UserId?desc?
- limit?100,?20;?
- ?
- ?explain?
- select?user.id,?user.nickname?
- from?(select?id,?userid?from?usergroup?where?groupid?=?1?order?by?userid?limit?100,?20)?t?
- left?join??user?on?t.UserId?=?user.id?;?
- ?
- ?explain?
- select?user.id,?user.nickname?
- from?(select?id,?userid?from?usergroup?where?groupid?=?1?order?by?userid?)?t?
- left?join??user?on?t.UserId?=?user.id??
- limit?100,?20;?
MYSQL实例第二句和第三句都使用到了子查询,不同之处再与,第二句是先得到20条数据,然后以此来与user表关联的
MYSQL实例4. 分析
MYSQL实例100000条数据情况下 :?
MYSQL实例先看第一句

再看第二句

第三句

从上面三幅图看,好像能看出点什么了.
MYSQL实例首先看他们的 rows,第二句最多,加起来有1000多了,另两句加起来都是996. 但是我想说的是,这里并不是看rows的和是多少. 正确的方式是,从id大的语句开始看,id相同的语句,从上到下依次执行.
MYSQL实例那先看第二句的id=2的语句和第一句的id=1的语句,一模一样的. 他们都是从usergroup表中筛选数据,并且能得到相同的结果集A.
MYSQL实例看来他们都是基于相同的结果集去进行操作,接下来就有区别了.
MYSQL实例先看第一句,再结果集A的基础上,去左连接表user,并筛选出最后的数据,返回给客户端.
MYSQL实例那第二句呢,是在A的基础上,再次筛选数据,得到需要的数据,然后拿这些数据,去与user表左连接,得到最终结果.
MYSQL实例从上面来看,执行计划中,第二种执行计划,更加高效.?
MYSQL实例?如果能够通过子查询,大幅度缩小查询范围,可以考虑使用子查询语句.?
MYSQL实例
? (编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|