來源:20Hui 發(fā)布時間:2018-11-01 10:14:14 閱讀量:1283
今天發(fā)現(xiàn)SQL語句執(zhí)行速度過慢,然后我就認(rèn)真看了看,用EXPLAIN看了一下
SQL
SELECT
count(*)
FROM
student_info AS s
LEFT JOIN class ON s.class_id = class.id
LEFT JOIN major AS m ON class.major_id = m.id
LEFT JOIN department AS d ON m.department_id = d.id
LEFT JOIN college AS c ON d.college_id = c.id
WHERE
s.student_number NOT IN (
SELECT
b.student_id
FROM
bed AS b
WHERE
b.student_id IS NOT NULL
ORDER BY
b.student_id
)
EXPLAIN
我發(fā)現(xiàn)這樣SQL的執(zhí)行速度太慢了,我就想著有什么辦法可以優(yōu)化。
網(wǎng)上那些count(1)、count(屬性),我都試過了,感覺變化不大
這個時候,我的師兄就給了一個建議,你不要使用IN,你使用EXIST,我之前就已經(jīng)知道IN的性能要差于EXIST,但是心理一直沒有一個概念,我就聽從師兄的建議,將NOT IN轉(zhuǎn)換為 NOT EXISTS,然后我又EXPLAIN一下。
SQL
SELECT
count(*)
FROM
student_info AS s
LEFT JOIN class ON s.class_id = class.id
LEFT JOIN major AS m ON class.major_id = m.id
LEFT JOIN department AS d ON m.department_id = d.id
LEFT JOIN college AS c ON d.college_id = c.id
WHERE
NOT EXISTS (
SELECT
b.student_id
FROM
bed AS b
WHERE
b.student_id IS NOT NULL
AND b.student_id = s.student_number
ORDER BY
b.student_id
)
EXPLAIN
通過對比我們就發(fā)現(xiàn),bed的索引,從rang變成ref,我又去百度了一下,他們兩個之間的差距。
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
震驚吧,他們之間相差這么多個量級。
然后他們之間的差距我們可以通過定義看出來
rang:range指的是有范圍的索引掃描,相對于index的全索引掃描,它有范圍限制,因此要優(yōu)于index。關(guān)于range比較容易理解,需要記住的是出現(xiàn)了range,則一定是基于索引的。同時除了顯而易見的between,and以及'>','<'外,in和or也是索引范圍掃描。
ref:出現(xiàn)該連接類型的條件是: 查找條件列使用了索引而且不為主鍵和unique。其實(shí),意思就是雖然使用了索引,但該索引列的值并不唯一,有重復(fù)。這樣即使使用索引快速查找到了第一條數(shù)據(jù),仍然不能停止,要進(jìn)行目標(biāo)值附近的小范圍掃描。但它的好處是它并不需要掃全表,因?yàn)樗饕怯行虻模幢阌兄貜?fù)值,也是在一個非常小的范圍內(nèi)掃描。
你們知道了吧,IN是走rang,就是最差的索引=沒有索引,而EXISTS走的ref,已經(jīng)算是比較好的檢索方式了。
記住了,以后不要再使用IN,要使用EXISTS了
---------------------
作者:20Hui
來源:CSDN
原文:https://blog.csdn.net/weixin_37645838/article/details/83585505
版權(quán)聲明:本文為博主原創(chuàng)文章,轉(zhuǎn)載請附上博文鏈接!