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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > 数据库 >内容正文

数据库

mysql in优化_MySQL的一次优化记录 (IN子查询和索引优化)

發(fā)布時(shí)間:2023/12/10 数据库 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql in优化_MySQL的一次优化记录 (IN子查询和索引优化) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

這兩天實(shí)習(xí)項(xiàng)目遇到一個(gè)網(wǎng)頁(yè)加載巨慢的問題(10多秒),然后定位到是一個(gè)MySQL查詢特別慢的語(yǔ)句引起的:

SELECT *

FROM (

SELECT DISTINCT t.vc_date, t.c_bankno, t.vc_bankacco, t.vc_moneytype, t.en_totalbala

, t.en_usablebala, t1.vc_nameinbank, date_format(t.D_IMPORTTIME, '%Y-%m-%d %H:%i:%S') AS D_IMPORTTIME

, t.vc_fundcode, t.c_datamode, t.vc_taskid, t.id, t.vc_projectname

, t.vc_projectcode, t1.c_accotype

, (

SELECT IF(vc_occurtime IS NULL, DATE_FORMAT(vc_occurdate, '%Y-%m-%d'), DATE_FORMAT(CONCAT(vc_occurdate, vc_occurtime), '%Y-%m-%d %H:%i:%S')) AS tradeTime

FROM tbanktradedetail_view

WHERE vc_bankacco = t.vc_bankacco

) AS d_tradetime, t3.vc_entry_caption AS C_ACCOTYPE_STR, t5.vc_entry_caption AS VC_BANKNAME, t4.vc_entry_caption AS VC_MONEYTYPE_STR

FROM tbankaccobala t

INNER JOIN tbankaccoinfo t1 ON t.vc_bankacco = t1.vc_bankacco

INNER JOIN (

SELECT vc_entry_value, vc_entry_caption

FROM ot_dic_tdictionaryentry

WHERE vc_entry_no = '5087'

) t3

ON t1.c_accotype = t3.vc_entry_value

INNER JOIN (

SELECT vc_entry_value, vc_entry_caption

FROM ot_dic_tdictionaryentry

WHERE vc_entry_no = '1004'

) t4

ON t1.VC_MONEYTYPE = t4.vc_entry_value

INNER JOIN (

SELECT vc_entry_value, vc_entry_caption

FROM ot_dic_tdictionaryentry

WHERE vc_entry_no = '1014'

) t5

ON t.c_bankno = t5.vc_entry_value

WHERE 1 = 1

AND t.id IN (

-- this query will take 4.6s:

-- SELECT SUBSTRING_INDEX(GROUP_CONCAT(id ORDER BY d_importtime DESC), ',', 1)

-- FROM tbankaccobala

-- GROUP BY vc_bankacco

-- but the following query only takes 1.1s:

SELECT hhhh from(

SELECT SUBSTRING_INDEX(GROUP_CONCAT(id ORDER BY d_importtime DESC), ',', 1) as hhhh

FROM tbankaccobala

GROUP BY vc_bankacco

) as sbstr

-- 對(duì)IN的子查詢做二次查詢

)

) t

WHERE 1 = 1

ORDER BY t.D_IMPORTTIME DESC

抽出查詢慢關(guān)鍵部分:

SELECT *

FROM (

SELECT DISTINCT t.vc_date, t.c_bankno, t.vc_bankacco, t.vc_moneytype, t.en_totalbala

-- 此處省略選擇多個(gè)列語(yǔ)句

FROM tbankaccobala t

-- 此處省略多張表連表查詢語(yǔ)句

WHERE 1 = 1

AND t.id IN (

-- 這個(gè)查詢需要3s:

SELECT SUBSTRING_INDEX(GROUP_CONCAT(id ORDER BY d_importtime DESC), ',', 1)

FROM tbankaccobala

GROUP BY vc_bankacco

)

) t

這個(gè)語(yǔ)句導(dǎo)致前端頁(yè)面10多秒才有響應(yīng)(但MySQL執(zhí)行顯示要4.6秒,phpMyAdmin也是10秒左右響應(yīng),為何?)

IN子查詢語(yǔ)句優(yōu)化

把IN語(yǔ)句里面的內(nèi)容改成下面這樣,只在外層再加一個(gè)select,就把3s的查詢縮短為0.006s:

SELECT hhhh from(

SELECT SUBSTRING_INDEX(GROUP_CONCAT(id ORDER BY d_importtime DESC), ',', 1) as hhhh

FROM tbankaccobala

GROUP BY vc_bankacco

) as sbstr

-- 對(duì)IN的子查詢做二次select,或者把IN改為JOIN都可以解決速度奇慢的問題

原語(yǔ)句空行處省略了一系列的其他表和 INNER JOIN 語(yǔ)句。一開始懷疑是多表的JOIN操作導(dǎo)致速度變慢,但刪去JOIN變成上面這段注釋掉的語(yǔ)句之后,速度依然非常慢,顯示要3s,于是猜測(cè) IN 才是導(dǎo)致速度變慢的主要因素,改后只要0.006s,嘖…

EXPLAIN 未優(yōu)化的語(yǔ)句:

(相關(guān)子查詢是使用外部查詢中的值的子查詢)

EXPLAIN 優(yōu)化的語(yǔ)句:

我的理解:優(yōu)化前,子查詢是相關(guān)子查詢,對(duì)于外部產(chǎn)生的每個(gè)值,都要執(zhí)行一次子查詢;優(yōu)化后,子查詢不再是相關(guān)子查詢,只需要執(zhí)行一次子查詢并緩存中間結(jié)果,外部查到的每個(gè)值去緩存的中間結(jié)果里比對(duì)一下就行了。

(有人說(shuō)是能不能用索引的原因——這么說(shuō)應(yīng)該是不對(duì)的)

完整查詢的后端響應(yīng)速度對(duì)比:

前:

后:

索引優(yōu)化

對(duì)于這么小的數(shù)據(jù)規(guī)模,時(shí)間還是太長(zhǎng)了… 看前面explain執(zhí)行計(jì)劃的截圖,嗯,沒有索引…

給t1的vc_bankacco加上索引之后

解釋執(zhí)行計(jì)劃:

查詢和網(wǎng)頁(yè)響應(yīng)用時(shí)大幅縮短:

再看sql里還有三個(gè)join:

用的都是ot_dic_tdictionaryentry這張表的t4.vc_entry_value字段,那么試著給這個(gè)字段也加上索引吧,然后用時(shí)如下:

是的,時(shí)間反而變長(zhǎng)了!

explain執(zhí)行計(jì)劃:

所以變慢原因是:

沒加vc_entry_value的索引時(shí),會(huì)先用vc_entry_no選出一個(gè)數(shù)量很小的表,再和t1做join,

而加了vc_entry_value的索引之后,MySQL就把這個(gè)索引用了起來(lái),join語(yǔ)句被優(yōu)化為先FirstMatch(ot_dic_tdictionaryentry),這產(chǎn)生了一個(gè)1713*1713=2934369行的中間結(jié)果(笛卡爾乘積),然后才使用vc_entry_no進(jìn)行where過濾。

所以索引不能亂加啊,加錯(cuò)了反而會(huì)導(dǎo)致性能下降!這個(gè)示例里的查詢要加索引只能在vc_entry_no上索引,而不能在vc_entry_value上!

這個(gè)示例中主要提升是IN子查詢語(yǔ)句的優(yōu)化。在使用索引的情況下,對(duì)IN子查詢做優(yōu)化前后的查詢時(shí)間分別是3.1s和0.16s

總結(jié)

以上是生活随笔為你收集整理的mysql in优化_MySQL的一次优化记录 (IN子查询和索引优化)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

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