日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

慢查询优化,我终于在生产踩到了这个坑!!

發(fā)布時間:2025/3/21 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 慢查询优化,我终于在生产踩到了这个坑!! 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

為什么會想取這樣一個標(biāo)題,因為看了理論上的慢查詢優(yōu)化,今天!!!終于在生產(chǎn)上實戰(zhàn)了。

一、慢sql一

問題發(fā)現(xiàn)

將應(yīng)用發(fā)布到生產(chǎn)環(huán)境后,前端頁面請求后臺API返回數(shù)據(jù),發(fā)現(xiàn)至少需要6s。查看到慢sql:

復(fù)現(xiàn)慢sql

執(zhí)行sql:

select?count(*)?from?sync\_block\_datawhere?unix\_timestamp(sync\_dt)?>=?1539101010AND?unix\_timestamp(sync\_dt)?<=?1539705810

查看耗時:

一共耗時為2658ms 查看執(zhí)行計劃:

explain?select?count(*)?from?sync\_block\_datawhere?unix\_timestamp(sync\_dt)?>=?1539101010AND?unix\_timestamp(sync\_dt)?<=?1539705810

執(zhí)行計劃結(jié)果:

優(yōu)化慢查詢一

sync_dt的類型為datetime類型。換另外一種sql寫法,直接通過比較日期而不是通過時間戳進(jìn)行比較。將sql中的時間戳轉(zhuǎn)化為日期,分別為2018-10-10 00:03:30和2018-10-17 00:03:30 執(zhí)行sql:

select?count(*)?from?sync\_block\_datawhere?sync\_dt?>=?"2018-10-10?00:03:30"AND?sync\_dt?<=?"2018-10-17?00:03:30"

查看耗時:

一共耗時419毫秒,和慢查詢相比速度提升六倍多 查看執(zhí)行計劃:

explain?select?count(*)?from?sync\_block\_datawhere?sync\_dt?>=?"2018-10-10?00:03:30"AND?sync\_dt?<=?"2018-10-17?00:03:30"

執(zhí)行計劃結(jié)果:

訪問頁面,優(yōu)化完成后請求時間平均為900毫秒

執(zhí)行計劃中慢查詢和快查詢唯一的區(qū)別就是type不一樣:慢查詢中type為index,快查詢中type為range。關(guān)注微信公眾號:Java技術(shù)棧,在后臺回復(fù):mysql,可以獲取我整理的 N 篇 MySQL 干貨。

優(yōu)化慢查詢二

這條sql的業(yè)務(wù)邏輯為統(tǒng)計出最近七天該表的數(shù)據(jù)量,可以去掉右邊的小于等于 執(zhí)行sql:

select?count(*)?from?sync\_block\_datawhere?sync_dt?>=?"2018-10-10?00:03:30"

查看耗時:

一共耗時275毫秒,又將查詢時間減少了一半 查看執(zhí)行計劃:

explain?select?count(*)?from?sync\_block\_datawhere?sync_dt?>=?"2018-10-10?00:03:30"

執(zhí)行計劃結(jié)果:

type仍是range。但是通過少比較一次將查詢速度提高一倍。

優(yōu)化慢查詢?nèi)?/h2>

新建一個bigint類型字段syncdtlong存儲syncdt的毫秒值,并在syncdt_long字段上建立索引 測試環(huán)境下:優(yōu)化慢查詢二sql

select?count(*)?from?copy\_sync\_block\_datawhere?sync\_dt?>="2018-10-10?13:15:02"

耗時為34毫秒 優(yōu)化慢查詢?nèi)齭ql

select?count(*)?from?copy\_sync\_block\_datawhere?sync\_dt_long?>=?1539148502916

耗時為22毫秒 測試環(huán)境中速度提升10毫秒左右

優(yōu)化慢查詢?nèi)齭ql測試小結(jié):在InnoDB存儲引擎下,比較bigint的效率高于datetime 完成三步優(yōu)化以后生產(chǎn)環(huán)境中請求耗時:

速度又快了200毫秒左右。通過給查詢的數(shù)據(jù)加10s緩存,響應(yīng)速度最快平均為20ms

explain使用介紹

id:執(zhí)行編號,標(biāo)識select所屬的行。如果在語句中沒子查詢或關(guān)聯(lián)查詢,只有唯一的select,每行都將顯示1。否則,內(nèi)層的select語句一般會順序編號,對應(yīng)于其在原始語句中的位置

select_type:顯示本行是簡單或復(fù)雜select。如果查詢有任何復(fù)雜的子查詢,則最外層標(biāo)記為PRIMARY(DERIVED、UNION、UNION RESUlT)

table:訪問引用哪個表(引用某個查詢,如“derived3”)

type:數(shù)據(jù)訪問/讀取操作類型(ALL、index、range、ref、eq_ref、const/system、NULL)

possible_keys:揭示哪一些索引可能有利于高效的查找

key:顯示mysql決定采用哪個索引來優(yōu)化查詢

key_len:顯示mysql在索引里使用的字節(jié)數(shù)

ref:顯示了之前的表在key列記錄的索引中查找值所用的列或常量

rows:為了找到所需的行而需要讀取的行數(shù),估算值,不精確。通過把所有rows列值相乘,可粗略估算整個查詢會檢查的行數(shù)。

Extra:額外信息,如using index、filesort等

重點(diǎn)關(guān)注type,type類型的不同竟然導(dǎo)致性能差六倍!!!

type顯示的是訪問類型,是較為重要的一個指標(biāo),結(jié)果值從好到壞依次是:system > const > eqref > ref > fulltext > refornull > indexmerge > uniquesubquery > indexsubquery > range > index > ALL ,一般來說,得保證查詢至少達(dá)到range級別,最好能達(dá)到ref。

All:最壞的情況,全表掃描

index:和全表掃描一樣。只是掃描表的時候按照索引次序進(jìn)行而不是行。主要優(yōu)點(diǎn)就是避免了排序, 但是開銷仍然非常大。如在Extra列看到Using index,說明正在使用覆蓋索引,只掃描索引的數(shù)據(jù),它比按索引次序全表掃描的開銷要小很多

range:范圍掃描,一個有限制的索引掃描。key 列顯示使用了哪個索引。當(dāng)使用=、 <>、>、>=、<、<=、IS NULL、<=>、BETWEEN 或者 IN 操作符,用常量比較關(guān)鍵字列時,可以使用 range |

ref:一種索引訪問,它返回所有匹配某個單個值的行。此類索引訪問只有當(dāng)使用非唯一性索引或唯一性索引非唯一性前綴時才會發(fā)生。這個類型跟eq_ref不同的是,它用在關(guān)聯(lián)操作只使用了索引的最左前綴,或者索引不是UNIQUE和PRIMARY KEY。ref可以用于使用=或<=>操作符的帶索引的列。

eq_ref:最多只返回一條符合條件的記錄。使用唯一性索引或主鍵查找時會發(fā)生 (高效)

const:當(dāng)確定最多只會有一行匹配的時候,MySQL優(yōu)化器會在查詢前讀取它而且只讀取一次,因此非常快。當(dāng)主鍵放入where子句時,mysql把這個查詢轉(zhuǎn)為一個常量(高效)

system:這是const連接類型的一種特例,表僅有一行滿足條件。

Null:意味說mysql能在優(yōu)化階段分解查詢語句,在執(zhí)行階段甚至用不到訪問表或索引(高效)

出現(xiàn)慢查詢的原因

在where子句中使用了函數(shù)操作 出現(xiàn)慢查詢的sql語句中使用了unix_timestamp函數(shù)統(tǒng)計出自'1970-01-01 00:00:00'的到當(dāng)前時間的秒數(shù)差。導(dǎo)致索引全掃描統(tǒng)計出近七天的數(shù)據(jù)量的。

解決方案

盡量避免在where子句中對字段進(jìn)行函數(shù)操作,這將導(dǎo)致存儲引擎放棄使用索引而進(jìn)行全表掃描。對于需要計算的值最好通過程序計算好傳入而不是在sql語句中做計算,比如這個sql中我們將當(dāng)前的日期和七天前的日期計算好傳入

后記

這個問題當(dāng)時在測試環(huán)境沒有發(fā)現(xiàn),測試環(huán)境的請求速度還是可以的。沒有被發(fā)現(xiàn)可以歸結(jié)為數(shù)據(jù)量。生產(chǎn)數(shù)據(jù)量為百萬級別,測試環(huán)境數(shù)據(jù)量為萬級,數(shù)據(jù)量差50倍,數(shù)據(jù)量的增大把慢查詢的問題也放大了。

二、慢sql二

因為線上出現(xiàn)了很明顯的請求響應(yīng)慢的問題,又去看了項目中的其他sql,發(fā)現(xiàn)還有sql執(zhí)行的效率比較低。

復(fù)現(xiàn)慢sql

執(zhí)行sql

select?FROM\_UNIXTIME(copyright\_apply\_time/1000,'%Y-%m-%d')?point,count(1)?numsfrom?resource\_info?where?copyright\_apply\_time?>=?1539336488355?and?copyright\_apply\_time?<=?1539941288355?group?by?point

查看耗時:

耗時為1123毫秒 查看執(zhí)行計劃:

explain?select?FROM\_UNIXTIME(copyright\_apply\_time/1000,'%Y-%m-%d')?point,count(1)?numsfrom?resource\_info?where?copyright\_apply\_time?>=?1539336488355?and?copyright\_apply\_time?<=?1539941288355?group?by?point

執(zhí)行計劃結(jié)果:

索引是命中了,但是extra字段中出現(xiàn)了Using temporary和Using filesort

優(yōu)化慢sql一

group by實質(zhì)是先排序后分組,也就是分組之前必排序。通過分組的時候禁止排序優(yōu)化sql 執(zhí)行sql:

select?FROM\_UNIXTIME(copyright\_apply\_time/1000,'%Y-%m-%d')?point,count(1)?numsfrom?resource\_info?where?copyright\_apply\_time?>=?1539336488355?and?copyright\_apply\_time?<=?1539941288355?group?by?point?order?by?null

查看耗時:

一共耗時1068毫秒,提高100毫秒左右,效果并不是特別明顯 查看執(zhí)行計劃:

extra字段已經(jīng)沒有Using filesort了,filesort表示通過對返回數(shù)據(jù)進(jìn)行排序。所有不是通過索引直接返回排序結(jié)果的排序都是FileSort排序,說明優(yōu)化后通過索引直接返回排序結(jié)果 Using temporary依然存在,出現(xiàn)Using temporary表示查詢有使用臨時表, 一般出現(xiàn)于排序, 分組和多表join的情況, 查詢效率不高, 仍需要進(jìn)行優(yōu)化,這里出現(xiàn)臨時表的原因是數(shù)據(jù)量過大使用了臨時表進(jìn)行分組運(yùn)算。

優(yōu)化慢sql二

慢查詢的sql業(yè)務(wù)邏輯為根據(jù)時間段分類統(tǒng)計出條件范圍內(nèi)各個時間段的數(shù)量 比如給定的條件范圍為2018-10-20~2018-10-27的時間戳,這條sql就會統(tǒng)計出2018-10-20~2018-10-27每天的數(shù)據(jù)增量。現(xiàn)在優(yōu)化成一天一天查,分別查七次數(shù)據(jù),去掉分組操作

select?FROM\_UNIXTIME(copyright\_apply\_time/1000,'%Y-%m-%d')?point,count(1)?numsfrom?resource\_info?where?copyright\_apply\_time?>=?1539855067355?and?copyright\_apply\_time?<=?1539941467355

查看耗時:

耗時為38毫秒,即使查7次所用時間也比1123毫秒少 查看執(zhí)行計劃:

extra字段中和慢查詢的extra相比少了Using temporary和Using filesort。完美就這樣第一次經(jīng)歷了真正的慢查詢以及慢查詢優(yōu)化,終于理論和實踐相結(jié)合了。

作者:何甜甜在嗎

https://juejin.im/post/5bcc2935f265da0ac66987c9

總結(jié)

以上是生活随笔為你收集整理的慢查询优化,我终于在生产踩到了这个坑!!的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。