前兩天接觸了乙個專案,裡面的乙個報表查詢功能,訪問資料庫很慢,嚴重時請求直接超時,寫的sql語句得有三四百行,真是頭疼,沒辦法,硬著頭皮,只能一段一段的分析sql,查詢sql慢的問題。解決思路就是使用explain 命令來檢視哪些表沒有用到索引。通過查詢終於找到問題所在,現記錄如下:
1、問題所在:
join on 條件後面不能使用or連線,造成索引失效,會全表掃瞄。
sql語句例項:
select
sp.id,
gcm.id as gcmid,
gcm.material_id
from
gt_supply_order sp
left join gt_supply_order_material gm on sp.id = gm.supply_order_id
left join gt_contract gc on sp.contract_id = gc.id
left join gt_orderform_goods nm on nm.order_id=gc.id or nm.id=gm.order_form_goods_id
left join gt_orderform_goods gcm on gcm.id = nm.id
or gcm.main_contract_goods_id = nm.id
and gcm.deleted = 0
where
sp.deleted = 0
and gm.deleted = 0
and sp.contract_id = # and sp.goods_class_name = # and sp.supply_order_status_enum=4
group by
sp.id,gcm.id
2、解決方案:
上面查詢(join on or)可以用 union 替換(索引有效),缺點sql語句長(相比效能問題還是可取的)
中間有個小插曲:
union 操作會對結果去重且排序,union all 不會去重
優化後的sql如下:
select a.id,gcm.id as gcmid,gcm.material_id from(
select
sp.id,
nm.id as nmid
from
gt_supply_order sp
left join gt_supply_order_material gm on sp.id = gm.supply_order_id
left join gt_contract gc on sp.contract_id = gc.id
left join gt_orderform_goods nm on nm.order_id=gc.id
where
sp.deleted = 0
and gm.deleted = 0 and nm.deleted=0
and sp.contract_id = 137957291194000 and sp.goods_class_name = '橋梁支座' and sp.supply_order_status_enum=4
union
select
sp.id,
nm.id as nmid
from
gt_supply_order sp
left join gt_supply_order_material gm on sp.id = gm.supply_order_id
left join gt_contract gc on sp.contract_id = gc.id
left join gt_orderform_goods nm on nm.id=gm.order_form_goods_id
where
sp.deleted = 0
and gm.deleted = 0 and nm.deleted=0
and sp.contract_id = 137957291194000 and sp.goods_class_name = '橋梁支座' and sp.supply_order_status_enum=4
)a left join gt_orderform_goods gcm on gcm.id = a.nmid
where gcm.id is not null
group by a.id,gcm.id
union
select b.id,gcm.id as gcmid,gcm.material_id from
( select
sp.id,
nm.id as nmid
from
gt_supply_order sp
left join gt_supply_order_material gm on sp.id = gm.supply_order_id
left join gt_contract gc on sp.contract_id = gc.id
left join gt_orderform_goods nm on nm.order_id=gc.id
where
sp.deleted = 0
and gm.deleted = 0 and nm.deleted=0
and sp.contract_id = 137957291194000 and sp.goods_class_name = '橋梁支座' and sp.supply_order_status_enum=4
union
select
sp.id,
nm.id as nmid
from
gt_supply_order sp
left join gt_supply_order_material gm on sp.id = gm.supply_order_id
left join gt_contract gc on sp.contract_id = gc.id
left join gt_orderform_goods nm on nm.id=gm.order_form_goods_id
where
sp.deleted = 0
and gm.deleted = 0 and nm.deleted=0
and sp.contract_id = 137957291194000 and sp.goods_class_name = '橋梁支座' and sp.supply_order_status_enum=4
)b left join gt_orderform_goods gcm on gcm.main_contract_goods_id = b.nmid
where gcm.id is not null
group by
b.id,gcm.id
3、總結:
(1)通過上面的優化,查詢速度由原來的77秒,提速到了0.107秒,提高700多倍,可見,sql優化是多麼的重要呀。
(2)這種優化方式可能不是最優的(sql語句太長),如有高人還有其他優化方式,希望可以交流,謝謝。
(3)有興趣的小夥伴可以測試下,歡迎交流。
mysql 連線 優化 (一)MySQL 連線優化
1.檢視連線引數 show variables mysql show variables like connect variable name value character set connection utf8 collation connection utf8 general ci conne...
join連線查詢之外連線和交叉連線
這個是個重點 join連線的分為內連線,外連線和交叉連線.外連線分左外連線 用到關鍵字left join,使用是以left jion關鍵字左邊的表作為基表並且全部展示,右邊的表和基表關聯的資訊展示 另一種展示方式,用 標示 select from db stu s left join db clas...
MySQL連線查詢之外連線操作詳解
前面一篇學習了內連線,本篇來學習外連線,外連線有左外連線和右外連線。本篇主要連線外連線和內連線的基本使用方法。外連線 outer join 是以某張表為主,取出裡面的所有記錄,然後每條與另外一張表進行連線。不管能不能匹配上條件,最終都會保留,也就是說,能匹配,正確保留 不能匹配,其他表的字段都置空 ...