《Mysql應(yīng)用Mysql - 性能優(yōu)化之子查詢》要點(diǎn):
本文介紹了Mysql應(yīng)用Mysql - 性能優(yōu)化之子查詢,希望對(duì)您有用。如果有疑問,可以聯(lián)系我們。
MYSQL實(shí)例當(dāng)Mysql Server的連接線程接收到Client發(fā)送過來的SQL請(qǐng)求后, 會(huì)經(jīng)過一系列的分解Parse, 進(jìn)行相應(yīng)的分析, 然后Mysql會(huì)通過查詢優(yōu)化器模塊, 根據(jù)該Sql所涉及到的數(shù)據(jù)表的相關(guān)統(tǒng)計(jì)信息進(jìn)行計(jì)算分析. 然后在得出一個(gè)Mysql自認(rèn)為最合理最優(yōu)化的數(shù)據(jù)訪問方式, 也就是我們常說的"執(zhí)行計(jì)劃", 然后根據(jù)所得到的執(zhí)行計(jì)劃通過調(diào)用存儲(chǔ)引擎接口來獲取相應(yīng)數(shù)據(jù). 再對(duì)存儲(chǔ)引擎返回的數(shù)據(jù)進(jìn)行相關(guān)的處理, 并一Client端所要求的格式作為結(jié)果集, 返回給Client.
MYSQL實(shí)例注 : 這里所說的統(tǒng)計(jì)數(shù)據(jù), 是我們通過 Analyze table命令通知Mysql對(duì)表的相關(guān)數(shù)據(jù)作分析之后, 所獲取到的一些數(shù)據(jù)統(tǒng)計(jì)量. 這些數(shù)據(jù)對(duì)Mysql優(yōu)化器而言是非常重要的, 優(yōu)化器所生成的執(zhí)行計(jì)劃的好壞, 主要是由這些統(tǒng)計(jì)數(shù)據(jù)所決定的.
MYSQL實(shí)例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?'創(chuàng)建時(shí)間'?
- )?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?'創(chuàng)建時(shí)間',?
- --?key?index_groupid(GroupId)?using?btree,?
- key?index_userid(groupid,?UserId)?using?btree?
- )?default?charset=utf8?comment?'用戶組表';?
MYSQL實(shí)例2. 準(zhǔn)備數(shù)據(jù)
?
- 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實(shí)例這里我插入了5000條數(shù)據(jù), group分了99個(gè)組, 隨機(jī)的.?
MYSQL實(shí)例?
MYSQL實(shí)例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實(shí)例第二句和第三句都使用到了子查詢, 不同之處再與, 第二句是先得到20條數(shù)據(jù), 然后以此來與user表關(guān)聯(lián)的
MYSQL實(shí)例?
MYSQL實(shí)例4. 分析
MYSQL實(shí)例100000條數(shù)據(jù)情況下 :?
MYSQL實(shí)例先看第一句
再看第二句
第三句
從上面三幅圖看, 好像能看出點(diǎn)什么了.
MYSQL實(shí)例首先看他們的 rows, 第二句最多, 加起來有1000多了, 另兩句加起來都是996. 但是我想說的是, 這里并不是看rows的和是多少. 正確的方式是, 從id大的語句開始看, id相同的語句, 從上到下依次執(zhí)行.
MYSQL實(shí)例那先看第二句的id=2的語句和第一句的id=1的語句, 一模一樣的. 他們都是從usergroup表中篩選數(shù)據(jù), 并且能得到相同的結(jié)果集A.
MYSQL實(shí)例看來他們都是基于相同的結(jié)果集去進(jìn)行操作, 接下來就有區(qū)別了.
MYSQL實(shí)例先看第一句, 再結(jié)果集A的基礎(chǔ)上, 去左連接表user, 并篩選出最后的數(shù)據(jù), 返回給客戶端.
MYSQL實(shí)例那第二句呢, 是在A的基礎(chǔ)上, 再次篩選數(shù)據(jù), 得到需要的數(shù)據(jù), 然后拿這些數(shù)據(jù), 去與user表左連接, 得到最終結(jié)果.
MYSQL實(shí)例從上面來看, 執(zhí)行計(jì)劃中, 第二種執(zhí)行計(jì)劃, 更加高效.?
MYSQL實(shí)例?如果能夠通過子查詢, 大幅度縮小查詢范圍, 可以考慮使用子查詢語句.?
MYSQL實(shí)例
?
轉(zhuǎn)載請(qǐng)注明本頁網(wǎng)址:
http://www.snjht.com/jiaocheng/5792.html