sql語句優化總結
數據庫優化的幾個原則:
1.盡量避免在列上做運算,這樣會導致索引失敗;
2.使用join是應該用小結果集驅動大結果集,同時把復雜的join查詢拆分成多個query。不然join的越多表,就會導致越多的鎖定和堵塞。
3.注意like模糊查詢的使用,避免使用%%,例如select * from a where name like '%de%';
代替語句:select * from a where name >= 'de' and name < 'df';
4.僅列出需要查詢的字段,不要使用select * from ...,節省內存;
5.使用批量插入語句,節省交互;
insert into a (id ,name) values(2,'a'), (3,'s');
6.limit基數比較大時,使用between ... and ...
7.不要使用rand函數隨機獲取記錄;
8.避免使用null ,這就需要在建表時,盡量設置為not null,提升查詢性能;
9,不要使用count(id),而應該是count(*)
10.不要做無謂的排序,盡可能在索引中完成排序;
我們先來看一個sql:
select ii.product_id, p.product_name, count(distinct pim.pallet_id) count_pallet_id, if(round(sum(itg.quantity),2) > -1 && round(sum(itg.quantity),2) < 0.005, 0, round(sum(itg.quantity),2)) quantity, round(ifnull(sum(itag.locked_quantity), 0.00000),2) locked_quantity, pc.container_unit_code_name, if(round(sum(itg.qoh),2) > -1 && round(sum(itg.qoh),2) < 0.005, 0, round(sum(itg.qoh),2)) qoh, round(ifnull(sum(itag.locked_qoh), 0.00000),2) locked_qoh, p.unit_code, p.unit_code_name from (select it.inventory_item_id item_id, sum(it.quantity) quantity, sum(it.real_quantity) qoh from ws_inventory_transaction it where it.enabled = 1 group by it.inventory_item_id ) itg left join (select ita.inventory_item_id item_id, sum(ita.quantity) locked_quantity, sum(ita.real_quantity) locked_qoh from ws_inventory_transaction_action ita where 1=1 and ita.type in ('locked', 'release') group by ita.inventory_item_id )itag on itg.item_id = itag.item_id inner join ws_inventory_item ii on itg.item_id = ii.inventory_item_id inner join ws_pallet_item_mapping pim on ii.inventory_item_id = pim.inventory_item_id inner join ws_product p on ii.product_id = p.product_id and p.status = 'OK' left join ws_product_container pc on ii.container_id = pc.container_id
//總起來說關聯太多表,設計表時可以多一些冗余字段,減少表之間的關聯查詢; where ii.inventory_type = 'raw_material' and ii.inventory_status = 'in_stock' and ii.facility_id = '25' and datediff(now(),ii.last_updated_time) < 3 //違反了第一個原則 and p.product_type = 'goods'
and p.product_name like '%果%' // 違反原則3
group by ii.product_id having qoh < 0.005 order by qoh desc
上面的sql我們在from 中使用了子查詢,這樣對查詢是非常不利的;
更好的一種做法是下面的語句:
select t.facility_id, f.facility_name, t.inventory_status, wis.inventory_status_name, t.inventory_type, t.product_type, t.product_id, p.product_name, t.container_id, t.unit_quantity, p.unit_code, p.unit_code_name, pc.container_unit_code_name, t.secret_key, sum(t.quantity) quantity, sum(t.real_quantity) real_quantity, sum(t.locked_quantity) locked_quantity, sum(t.locked_real_quantity) locked_real_quantity from ( select ii.facility_id, ii.inventory_status, ii.inventory_type, ii.product_type, ii.product_id, ii.container_id, ii.unit_quantity, ita.secret_key, ii.quantity quantity, ii.real_quantity real_quantity, sum(ita.quantity) locked_quantity, sum(ita.real_quantity) locked_real_quantity from ws_inventory_item ii inner join ws_inventory_transaction_action ita on ii.inventory_item_id = ita.inventory_item_id where ii.facility_id = '{$facility_id}' and ii.inventory_status = '{$inventory_status}' and ii.product_type = '{$product_type}' and ii.inventory_type = '{$inventory_type}' and ii.locked_real_quantity > 0 and ita.type in ('locked', 'release') group by ii.product_id, ita.secret_key, ii.container_id, ita.inventory_item_id having locked_real_quantity > 0 ) as t inner join ws_product p on t.product_id = p.product_id left join ws_facility f on t.facility_id = f.facility_id left join ws_inventory_status wis on wis.inventory_status = t.inventory_status left join ws_product_container pc on pc.container_id = t.container_id group by t.product_id, t.secret_key, t.container_id
注意:
1、from 語句中一定不要使用子查詢;
2、使用更多的where加以限制,縮小查找范圍;
3、合理利用索引;
4、通過explain查看sql性能;
相關優化可以借鑒:http://blog.csdn.net/csh624366188/article/details/8457749
