[英]Mysql query performance is slow, need help in optimization
我有4個表:發貨(200K記錄),商店(45記錄),product_stores(8K記錄),區(698記錄)。 以下查詢需要很長時間才能執行(12秒):
SELECT `s`. * , `p`.`productCode` , `p`.`productName` , `st`.`name` AS `storeName` , `d`.`name` AS `districtName`
FROM `shipments` AS `s`
JOIN `product_stores` AS `p` ON s.productStoreId = p.id
JOIN `stores` AS `st` ON s.storeId = st.id
LEFT JOIN `districts` AS `d` ON s.districtId = d.id
WHERE (s.storeId IN (1, 2, 3, 4, 6, 9, 14, 16, 22, 26, 30))
GROUP BY `s`.`id`
ORDER BY `s`.`id` DESC
LIMIT 100
EXPLAIN查詢返回以下結果:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE st ALL PRIMARY NULL NULL NULL 45 Using where; Using temporary; Using filesort
1 SIMPLE s ref fk_shipments_stores1_idx,fk_shipments_product_stor... fk_shipments_stores1_idx 4 st.id 482
1 SIMPLE p eq_ref PRIMARY PRIMARY 4 s.productStoreId 1
1 SIMPLE d eq_ref PRIMARY PRIMARY 4 s.districtId 1
(我使用的是mysql 5.0.95)
這是表結構:
您的查詢將足夠慢,因為您的查詢加入策略需要太多的I / O.
讓我為您的查詢I / O草擬計算,以便理解如下:
1. JOIN shipments (200K records) and product_stores (8K records)
200K x 8 K = 1600K I/O
2. Then, JOIN to stores (45 records)
1600K x 45 = 75000K I/O
3. Then, JOIN to districts (698 records)
75000K x 698 = 50256000K I/O
4. Then, Filter the result (by storeId), so need to read the result I/O again
50256000K + 50256000K = **100512000K I/O (TOTAL I/O)**
So, total I/O on memory of your query is 100512000K I/O.
要提高查詢效果,您需要重新考慮您的查詢加入計划/策略
例如:
1. Read shipments (200K records) and Filter storeId (assume: result is 8 record)
200K + 8 = 208K I/O
2. Then, JOIN to product_stores (8K records)
208K x 8K = 1664K I/O
3. Then, JOIN to stores (45 records)
1664K x 45K = 74880K I/O
4. Then, finally JOIN to districts (698 records).
74880K + 698 = **52266240 I/O (TOTAL I/O)**
So, total I/O on memory of your query is 52266240 I/O. (greatly reduce I/O then ever)
因此,您可以通過以上方式提高查詢性能。
我希望它可以幫助你。
我只是在嘗試解決方案。 希望這可以減少執行時間
SELECT `s`. * , `ps`.`productCode` , `ps`.`productName` , `st`.`name` AS `storeName` , `d`.`name` AS `shipToDistrictName`
FROM `shipments` AS `s`
JOIN `product_stores` AS `ps` ON s.productStoreId = ps.id
JOIN `stores` AS `st` ON (s.storeId = st.id AND s.storeId IN (1, 2, 3, 4, 6, 9, 14, 16, 22, 26, 30))
LEFT JOIN `districts` AS `d` ON s.shipToDistrictId = d.id
GROUP BY `s`.`id`
ORDER BY `s`.`id` DESC
LIMIT 100
這將限制記錄的數量僅限於那些只有那些需要的記錄,並進一步與減少的記錄數連接,從而減少執行時間。
希望能幫助到你...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.