2015-02-08 239 views
1

我有非常大的客戶數據庫。在添加ORDER BY之前,此查詢是可以的。我怎樣才能優化我的查詢速度?爲什麼這個INNER JOIN/ORDER BY mysql查詢太慢?

$sql = "SELECT * FROM customers 
LEFT JOIN ids ON customer_ids.customer_id = customers.customer_id AND ids.type = '10' 
ORDER BY customers.name LIMIT 10";

ids.typecustomers.name是我的指標

解釋查詢

 
id select_type table  type possible_keys key  key_len  ref  rows Extra 
1 SIMPLE  customers ALL  NULL   NULL NULL  NULL 955  Using temporary; Using filesort 
1 SIMPLE  ids  ALL  type   NULL NULL  NULL 3551 Using where; Using join buffer (Block Nested Loop)
+0

如果您可以將其他字段添加好的索引,請這樣做。這是有道理的,因爲按順序排列,它需要整個結果集才能重新排列。另外,你的主鍵是什麼? – 2015-02-08 03:21:20

+3

您的查詢語法錯誤。 'customer_ids'沒有被定義。 – 2015-02-08 03:23:42

+0

他指的是customer_ids被用在他的連接標準中,但事實上並不是加入的表中的一個。你能在上面的查詢中顯示EXPLAIN的結果嗎? – BK435 2015-02-08 03:51:28

回答

1

(我假設你想鍵入ids.customer_id = customer.customer_id而不是customer_ids.customer_id)

沒有ORDER BY mysql抓住了10型(索引)的前10個ID,擡起頭看着cu對他們來說,他們已經完成了。 (請注意,LEFT JOIN這裏真的是一個INNER JOIN因爲連接條件將僅保持有兩個表中的匹配行)

與ORDER BY MySQL是可能獲取所有類型= 10個客戶,然後排序他們通過名字找到前10個。

您可以通過反規範化客戶表(將該類型複製到客戶記錄)或創建映射表來保存元組來加快速度。無論哪種情況,請在(type, name)上添加索引。如果使用映射表,請使用它與客戶和ID進行三方聯接。

如果type = 10是相當常見的,那麼您也可以強制查詢按照名稱來遍歷customers表,並通過STRAIGHT JOIN檢查每個類型。它不會像複合指數那樣快,但它會比提起所有比賽更快。

如上所示,對查詢運行EXPLAIN以查看mysql正在使用的查詢計劃。

+0

什麼是「STRAIGHT」連接? – 2015-02-08 07:49:48

+0

直接連接是一個mysql連接類型,用於遍歷左表並連接右表找到的行。與查詢優化器選擇讀取表的順序的其他連接不同,直接連接允許程序員指定。 – Andras 2015-02-08 07:56:43

+0

我添加了EXPLAIN查詢記錄 – lingo 2015-02-08 14:58:46

0

LEFT是問題所在。通過說LEFT JOIN,您暗示某些customersids中可能沒有相應的行。而且,您願意接受NULL的字段來代替這樣的ids行。

如果不是這種情況,請移除LEFT。然後確保你有一個ids的索引開始type。此外,customers必須具有從customer_id開始的索引(可能是PRIMARY KEY)。有了這些,優化器可以從ids開始,在type上過濾,從而減少了工作量。

但是,它仍然必須收集大量的行之前做排序(ORDER BY);只有這樣才能交付10個(LIMIT)。

當你在它的時候,將INDEX(customer_id)加到ids - 這就是殺死LEFT版本的性能。