如何優(yōu)化sql查詢效率 sql語(yǔ)句執(zhí)行過(guò)程分析?
sql語(yǔ)句執(zhí)行過(guò)程分析?當(dāng)客戶端把SQL語(yǔ)句傳送到服務(wù)器后,服務(wù)器進(jìn)程會(huì)對(duì)該語(yǔ)句并且解析。同理可知,這個(gè)解析的工作,都是在服務(wù)器端所并且的??墒沁@只是因?yàn)橐粋€(gè)解析的動(dòng)作,但是,其會(huì)做很多“小動(dòng)作”。緩
sql語(yǔ)句執(zhí)行過(guò)程分析?
當(dāng)客戶端把SQL語(yǔ)句傳送到服務(wù)器后,服務(wù)器進(jìn)程會(huì)對(duì)該語(yǔ)句并且解析。同理可知,這個(gè)解析的工作,都是在服務(wù)器端所并且的??墒沁@只是因?yàn)橐粋€(gè)解析的動(dòng)作,但是,其會(huì)做很多“小動(dòng)作”。緩存中(librarycache)。
服務(wù)器進(jìn)程在接到客戶端傳送回來(lái)的SQL語(yǔ)句時(shí),絕對(duì)不會(huì)真接去數(shù)據(jù)庫(kù)網(wǎng)上查詢。反而會(huì)先在數(shù)據(jù)庫(kù)的高速緩存中去查看,是否是必然是一樣的語(yǔ)句的執(zhí)行計(jì)劃。如果不是在數(shù)據(jù)高速緩存中不能找到不同語(yǔ)句的執(zhí)行計(jì)劃,則服務(wù)器進(jìn)程都會(huì)直接負(fù)責(zé)執(zhí)行這個(gè)SQL語(yǔ)句,省掉現(xiàn)的工作。所以才,區(qū)分出口下高速數(shù)據(jù)緩存的話,可以提高SQL語(yǔ)句的查詢效率。另外一方面是從內(nèi)存中讀取數(shù)據(jù)要比從硬盤(pán)中的數(shù)據(jù)文件中讀取數(shù)據(jù)效率要高,另外一方面,確實(shí)是只不過(guò)這個(gè)語(yǔ)句解析的原因。
sql語(yǔ)句查詢速度是1分鐘慢嗎?
可以系統(tǒng)優(yōu)化,我們最近在做的是在用3臺(tái)30G內(nèi)存,12核心的虛擬機(jī)。對(duì)此6億1千4百萬(wàn)的數(shù)據(jù)(Mysql中是130G,parquet格式是30G),負(fù)責(zé)執(zhí)行多字段分組聚合某字段count(distinct)工程浩大在30秒左右,而是對(duì)普通地網(wǎng)站查詢需要的時(shí)間在2秒內(nèi)。所以我我覺(jué)著是對(duì)你的情況,優(yōu)化系統(tǒng)空間還太大
如何分析一條SQL的性能?
在做性能測(cè)試中經(jīng)常會(huì)遇上一些sql的問(wèn)題,反正做對(duì)比測(cè)試這幾年遇到問(wèn)題至少那就數(shù)據(jù)庫(kù)這塊,要么是IO高不是的話就是cpu高,所以才對(duì)數(shù)據(jù)的優(yōu)化在性能測(cè)試過(guò)程中占下著很重要的是的地方,下面我就介紹一些msyql性能調(diào)優(yōu)過(guò)程中每天都要用的三件利器:
1、慢網(wǎng)上查詢(總結(jié)直接出現(xiàn)出問(wèn)題的sql)
2、Explain(會(huì)顯示了mysql使用方法索引來(lái)處理select語(yǔ)句包括連接到表。這個(gè)可以好處你選擇更好的索引和寫(xiě)一段更優(yōu)化系統(tǒng)的查詢語(yǔ)句)
3、Profile(網(wǎng)站查詢到SQL會(huì)負(fù)責(zé)執(zhí)行多少時(shí)間,并看得出CPU/Memory建議使用量,想執(zhí)行過(guò)程中Systemlock,Tablelock花多少時(shí)間等等.)
是需要我們先講一講mysql的慢網(wǎng)上查詢
1,配置再開(kāi)啟
Linux:
在mysql配置文件中減少
log-slow-queries/var/lib/mysql/slowquery.log(重新指定日志文件存放位置,這個(gè)可以為空,系統(tǒng)會(huì)給一個(gè)缺省的文件host_name-
slow.log)
shorter_query_time2(資料記錄超過(guò)的時(shí)間,默認(rèn)為10s)
log-queries-actually-using-indexes(log下來(lái)沒(méi)有建議使用索引的query,這個(gè)可以依據(jù)情況決定有無(wú)開(kāi)啟)
log-long-format(如果不是設(shè)置里了,所有沒(méi)有建議使用索引的查詢也將被留下記錄)Windows:
在的[mysqld]再添加不勝感激語(yǔ)句:
log-slow-queriesE:webmysqllogmysqlslowquery.loglong_query_time2(其他參數(shù)睽車志)
2,欄里點(diǎn)
Linux:
可以使用mysql從網(wǎng)上下載命令mysqldumpslow查看
常用命令
-sORDERwhatcansorthe(t,as,l,al,r,aretc),as'isdefault
-tNUMjustshowthe topnqueries
-gPATTERNgrep:onlyconsiderstmtswhetherincludethisstringeg:
s,是order的順序,那就證明寫(xiě)的太少詳細(xì),俺用過(guò)去,以及看了代碼,比較多有c,t,l,r和ac,at,al,ar,分別是按照query次數(shù),時(shí)間,lock的時(shí)間和直接返回的記錄數(shù)來(lái)排序,前面加了a的時(shí)倒序-t,是hotn的意思,即為直接返回前面多少條的數(shù)據(jù)-g,后邊可以不寫(xiě)一個(gè)正則自動(dòng)分配模式,大小寫(xiě)字母不敏感的
mysqldumpslow-sc-t20host-slow.log
mysqldumpslow-sr-t20host-slow.log
本案所涉命令可以看出訪問(wèn)次數(shù)最少的20個(gè)sql語(yǔ)句和直接返回留下記錄集最多的20個(gè)sql。
mysqldumpslow-t10-st-g“l(fā)eftjoin”host-slow.log這個(gè)是通過(guò)時(shí)間返回前10條里面成分左連接到的sql語(yǔ)句。
接下來(lái)的事情那是prepare
使用方法:
想執(zhí)行EXPLAINSELECT*fromres_userORDER BYmodifiedtimeLIMIT0,1000能夠得到如下結(jié)果:
不顯示結(jié)果總結(jié):
table|type|possible_keys|key|key_len|ref|rows|Extra
EXPLAIN列的解釋:
table
總是顯示這一行的數(shù)據(jù)是麻煩問(wèn)下哪張表的
type
這是最重要的列,會(huì)顯示連接到不使用了何種類型。從最好是到最差的連接類型為const、eq_reg、ref、range、indexhe和ALL
possible_keys
顯示很有可能應(yīng)用在這張表中的索引。假如為空,就沒(méi)很可能的索引。這個(gè)可以為相關(guān)的域從WHERE語(yǔ)句中選擇一個(gè)適合的語(yǔ)句
key
實(shí)際中不使用的索引。如果沒(méi)有為NULL,則也沒(méi)建議使用索引。很少的情況下,MYSQL會(huì)你選擇優(yōu)化系統(tǒng)不足的索引。狀況下,也可以在SELECT語(yǔ)句中不使用USE INDEX(indexname)來(lái)滿使用一個(gè)索引也可以用IGNOREINDEX(indexname)來(lái)強(qiáng)制MYSQL看出索引
key_len
不使用的索引的長(zhǎng)度。在不傷亡精確性的情況下,長(zhǎng)度越短越好
ref
總是顯示索引的哪一列被在用了,如果沒(méi)有可能的話,是一個(gè)常數(shù)
rows
MYSQL其實(shí)要檢查的利用前往只是請(qǐng)求數(shù)據(jù)的行數(shù)Extra麻煩問(wèn)下MYSQL要如何解三角形可以查詢的額外信息。將在表4.3中討論到,但這里可以看到的壞的例子是Usingpermanent和Usingfilesort,意思MYSQL根本就不可能肯定不能在用索引,結(jié)果是數(shù)據(jù)庫(kù)檢索會(huì)很慢
extra列直接返回的描述的意義
Distinct
若是MYSQL找到了與行相組織自動(dòng)分配的行,就再次搜索了
Notexists
MYSQL優(yōu)化系統(tǒng)了LEFTJOIN,若是它能找到了看操作LEFT JOIN標(biāo)準(zhǔn)的行,就不再直接搜索了
Rangecheckedaftereach
Record(indexmap:#)
還沒(méi)有找到理想的索引,而這對(duì)從前面表中來(lái)的每一個(gè)行組合,MYSQL檢查不使用哪個(gè)索引,王用它來(lái)從表中趕往行。這是在用索引的最慢的連接之一
Usingfilesort
看見(jiàn)這個(gè)的時(shí)候,網(wǎng)上查詢就不需要優(yōu)化了。MYSQL必須并且額外的步驟來(lái)發(fā)現(xiàn)到如何對(duì)回的行排序。它依據(jù)什么連接上類型這些存儲(chǔ)排序鍵值和不兼容條件的全部行的行指針來(lái)排序完全行
Usingindex
列數(shù)據(jù)是從不僅僅建議使用了索引中的信息而還沒(méi)有讀取文件實(shí)際中的行動(dòng)的表前往的,這再一次發(fā)生在對(duì)表的全部的請(qǐng)求列全是同一個(gè)索引的部分的時(shí)候
Usingtemporarily
看到這個(gè)的時(shí)候,去查詢必須優(yōu)化了。這里,MYSQL是需要?jiǎng)?chuàng)建家族一個(gè)正式
表來(lái)存儲(chǔ)結(jié)果,這大多數(shù)再一次發(fā)生在對(duì)不同的列集進(jìn)行ORDER BY上,而不是GROUP BY上
Whereused
在用了WHERE從句來(lái)限制哪些已臨與下一張表匹配或是是趕往給用戶。假如我也不想直接返回表中的徹底行,但是再連接類型ALL或index,這可能會(huì)突然發(fā)生,的或是網(wǎng)上查詢有問(wèn)題
不同連接類型的解釋(明確的效率高低的順序排序)
system
表只能一行:system表。這是const連接類型的特殊情況
const
表中的一個(gè)記錄的大值能夠不兼容這個(gè)查詢(索引可以是主鍵或紫月族索引)。因?yàn)閮H有一行,這個(gè)值不好算那就是常數(shù),而且MYSQL先讀這個(gè)值然后把把它當(dāng)做常數(shù)來(lái)對(duì)待
eq_ref
在直接連接中,MYSQL在查詢時(shí),從前面的表中,對(duì)每一個(gè)記錄的同盟都從表中讀取數(shù)據(jù)一個(gè)記錄,它在可以查詢不使用了索引為主鍵或唯一的一鍵的全部時(shí)使用
ref
這個(gè)再連接類型只有在網(wǎng)站查詢建議使用了不是沒(méi)有或主鍵的鍵也可以是這些類型的部分(比如,用來(lái)最左邊前綴)時(shí)發(fā)生。是對(duì)之前的表的每一個(gè)行合作,徹底記錄都將從表中讀得出。這個(gè)類型十分嚴(yán)重依賴感于根據(jù)索引自動(dòng)分配的記錄多少—越少越好
range
這個(gè)再連接類型不使用索引返回一個(gè)范圍中的行,.例如使用gt或lt;查看東西時(shí)發(fā)生了什么的情況
index
這個(gè)連接類型對(duì)前面的表中的每一個(gè)記錄同盟參與全部系統(tǒng)掃描(比ALL好,而且索引一般大于表數(shù)據(jù))
ALL
這個(gè)再連接類型相對(duì)于前面的每一個(gè)記錄組建接受幾乎掃描,這象也很糟糕,應(yīng)該注意盡量避免
況且那是profile
我們這個(gè)可以先使用
mysqlgtSELECT@@profiling
-------------
|@@profiling|
-------------
|0|
-------------
1rowintoset(0.00sec)來(lái)欄里點(diǎn)有無(wú)早重設(shè)profile,要是profilng
值為0,是可以是從
mysqlgtSETprofiling1
Query就ok啦,0rowsaffected(0.00sec)
mysqlgtSELECT@@profiling
-------------
|@@profiling|
-------------
|1|
-------------
1rowoutsideset(0.00sec)
來(lái)禁用。啟用profiling之后,我們先執(zhí)行一條查詢語(yǔ)句,例如:
SELECT*fromres_userORDER BYmodifiedtimeLIMIT
0,1000
mysqlgtshowprofiles
---------------------------------------------------------------
--------------------
|Query_ID|Duration|Query|
---------------------------------------------------------------
--------------------
|1|0.00012200|SELECT@@profiling|
|2|1.54582000|selectres_idFROMbiol_user
ORDER BYmodifiedtimeLIMIT0,3|
---------------------------------------------------------------
--------------------
2 rowsinset(0.00sec)注意:Query_ID表示剛執(zhí)行的查詢語(yǔ)句
mysqlgtshowprofileforquery2
------------------------------------------
|Status|Duration|
------------------------------------------
|starting|0.000013|
|checkingquery cacheforquery|0.000035|
|Openingtables|0.000009|
|Systemlock|0.000002|
|Tablelock|0.000015|
|init|0.000011|
|optimizing|0.000003|
|statistics|0.000006|
|preparing|0.000006|
|executing|0.000001|
|Sortingresult|1.545565|
|Sendingdata|0.000038|
|end|0.000003|
|queryend|0.000003|
|freeingitems|0.000069|
|storingresultinquery cache|0.000004|
|loggingmovequery|0.000001|
|loggingslowquery|0.000033|
|sanitationgood|0.000003|
------------------------------------------
19rowsofset(0.00sec)
結(jié)論:可以猜想此條查詢語(yǔ)句的執(zhí)行過(guò)程及先執(zhí)行時(shí)間,總的時(shí)間約為1.545s。這時(shí)候我們?cè)傧雸?zhí)行四次。
mysqlgtSELECTres我的idfromres_userORDER BYmodifiedtimeLIMIT0,3
---------
|res_id|
---------
|1000305|
|1000322|
|1000323|
---------
3rowsofset(0.00sec)
mysqlgtshowprofiles
-----------------------------------------------------------------------------------
|Query_ID | Duration | Query|
-----------------------------------------------------------------------------------
|1|0.00012200|SELECT@@profiling|
|2|1.54582000|SELECTres帳號(hào)returningres_userORDER BYmodifiedtimeLIMIT0,3|
|3|0.00006500|SELECTresidoutsideres_userORDER BYmodifiedtimeLIMIT0,3|
-----------------------------------------------------------------------------------
3rowsoutsideset(0.00sec)
mysqlgtshowprofileafterquery3
------------------------------------------
|Status | Duration |
------------------------------------------
|starting|0.000013|
|checkingquerycachewhilequery|0.000005|
|checkingprivilegesoncached|0.000003|
|sendingcachedresultneedclien|0.000040|
|loggingslowquery|0.000002|
|cleangood|0.000002|
------------------------------------------
6rowsacrossset(0.00sec)(再注意黃色標(biāo)記的地方)
結(jié)論:一眼就可以看出此次一次網(wǎng)站查詢因?yàn)榍耙淮蔚牟樵兩沙恋砹薱ache,所以我剛才不需要從數(shù)據(jù)庫(kù)文件中再度讀取數(shù)據(jù)只是然后從緩存中讀取數(shù)據(jù),結(jié)果查詢時(shí)間比一次快多了(第二次可以查詢用不1.5秒而決賽當(dāng)天用了不出來(lái)5毫秒)。