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