【工作隨手記】mysql優化之1

原SQL:

SELECT
p.id,
p.NAME,
p.idcard,
p.phone,
p.plate,
p.FAMILY_NO
FROM
t_person_info p
WHERE
p.id IN ( SELECT id FROM t_person_info WHERE FAMILY_NO = ( SELECT FAMILY_NO FROM t_person_info WHERE id = '1561155127086411776' ) )
OR p.id = '1561155127086411776'

執行計劃:

耗時:

2.4秒

優化思路:
將人員的直接查出來,只有1條數據作爲驅動表,再用戶口號去關聯原表。
優化後的SQL:

SELECT
p.id,
p.NAME,
p.idcard,
p.phone,
p.plate,
p.FAMILY_NO
FROM
t_person_info p
right JOIN (select * from t_person_info where id = '1561155127086411776') p2 on p.FAMILY_NO = p2.FAMILY_NO

執行計劃

耗時:

0.03秒

成功避免了兩個子查詢以及79萬表的全表掃描。

結論
永遠不要輕易使用【in子查詢】,由於in子查詢總是以外層查詢的table作爲驅動表,所以如果想用in子查詢的話,一定要將外層查詢的結果集降下來,降低io次數,降低nested loop循環次數,即:永遠用小結果集驅動大的結果集。
之前的SQL就是以大表t_person_info作爲驅動表進行nested loop,該表數據越大,效率越慢。

如sql

SELECT
p.id,
p.NAME,
p.idcard,
p.phone,
p.plate,
p.FAMILY_NO
FROM
t_person_info p
WHERE
p.id IN ( SELECT id FROM t_person_info WHERE FAMILY_NO = '11697717')
and p.id = '1561155127086411776'

mysql優化器自動謂詞下推,等價於:

SELECT
p.id,
p.NAME,
p.idcard,
p.phone,
p.plate,
p.FAMILY_NO
FROM
(select * from t_person_info where id = '1561155127086411776') p
WHERE
p.id IN ( SELECT id FROM t_person_info WHERE FAMILY_NO = '11697717')

這樣驅動表結果集降到最低,效率也就提高了。這裏只是舉例,這條SQL並不符合業務場景。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章