![](/img/trans.png)
[英]MySql , JOIN and Group By query is Using temporary and Filesort
[英]MySQL performance, inner join, how to avoid Using temporary and filesort
我有一張桌子1和桌子2。
表1 PARTNUM - ID_BRAND partnum是主鍵id_brand是“索引”
表2 ID_BRAND - BRAND_NAME id_brand是主鍵brand_name是“已編入索引”
表1包含100萬條記錄,表2包含1.000條記錄。
我正在嘗試使用EXPLAIN優化一些查詢,經過大量嘗試后我已經走到了死胡同。
EXPLAIN
SELECT pm.partnum, pb.brand_name
FROM products_main AS pm
LEFT JOIN products_brands AS pb ON pm.id_brand=pb.id_brand
ORDER BY pb.brand ASC
LIMIT 0, 10
查詢返回此執行計划:
ID, SELECT_TYPE, TABLE, TYPE, POSSIBLE_KEYS, KEY, KEY_LEN , REF, ROWS, EXTRA
1, SIMPLE, pm, range, PRIMARY, PRIMARY, 1, , 1000000, Using where; Using temporary; Using filesort
1, SIMPLE, pb, ref, PRIMARY, PRIMARY, 4, demo.pm.id_pbrand, 1,
MySQL查詢優化器在執行計划中顯示臨時+文件排序。 我怎么能避免這個?
“EVIL”位於ORDER BY pb.brand ASC中 。 訂購外部領域似乎是瓶頸。
嘗試使用子查詢替換連接。 MySQL的優化器很糟糕; 子查詢通常比連接提供更好的性能。
這個問題有些過時,但我確實找到了,其他人也是如此。
如果ORDER BY或GROUP BY包含連接隊列中第一個表以外的表中的列,則Mysql使用臨時。
所以你只需要通過使用STRAIGHT_JOIN來反轉連接順序,以繞過優化器發明的順序:
SELECT STRAIGHT_JOIN pm.partnum, pb.brand_name
FROM products_brands AS pb
RIGHT JOIN products_main AS pm ON pm.id_brand=pb.id_brand
ORDER BY pb.brand ASC
LIMIT 0, 10
還要確保將max_heap_table_size和tmp_table_size變量設置為足以存儲結果的數字:
SET global tmp_table_size=100000000;
SET global max_heap_table_size=100000000;
- 在此示例中為100 MB。 這些也可以在my.cnf配置文件中設置。
首先,嘗試更改products_brands表上的索引。 刪除brand_name
上的現有brand_name
,然后創建一個新名稱:
ALTER TABLE products_brands ADD INDEX newIdx (brand_name, id_brand)
然后,該表將具有“orderedByBrandName”索引,其中包含加入所需的ID,您可以嘗試:
EXPLAIN
SELECT pb.brand_name, pm.partnum
FROM products_brands AS pb
LEFT JOIN products_main AS pm ON pb.id_brand = pm.id_brand
LIMIT 0, 10
請注意,我還更改了查詢中表的順序,因此您可以從小表開始。
首先,我質疑外部連接的使用,因為order by操作在rhs上,而左連接注入的NULL可能會對它造成嚴重破壞。
無論如何,加速此查詢的最簡單方法是pb.id_brand和pb.brand上的覆蓋索引。 這將允許使用連接條件“使用索引”評估訂單。 另一種方法是找到一些方法來減少傳遞給order-by的中間結果的大小。
盡管如此,外部聯接,順序和限制的組合讓我想知道你究竟要查詢的是什么,以及是否有更好的表達查詢本身的方式。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.