簡體   English   中英

MySQL性能,內連接,如何避免使用臨時和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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM