2013-02-18 66 views
2

我試圖優化查詢速度慢,大約需要5分鐘,我的服務器在我的電腦上運行,大約相同的時間(即具有RAM的8GB)慢MySQL的子查詢

SELECT 
    buyer_id as bid, 
    date_sold as dsold, 
    (
     SELECT seller_id 
     FROM sale 
     WHERE buyer_id = bid 
     ORDER BY date_acquired 
     LIMIT 1 
    ) as sid 
from sale 
WHERE seller_id = 3585328; 

我我爲這個查詢創建了一個測試索引。

| sale |   1 | test    |   1 | buyer_id   | A   |  4900222 |  NULL | NULL |  | BTREE  |   | 
| sale |   1 | test    |   2 | date_acquired | A   | 14700667 |  NULL | NULL |  | BTREE  |   | 

當我運行一個解釋,我得到

mysql> EXPLAIN SELECT buyer_id as bid,date_sold as dsold, (SELECT seller_id FROM sale WHERE buyer_id = bid ORDER BY date_acquired LIMIT 1) as sid from sale WHERE seller_id = 3585328; 
+----+--------------------+-------+------+---------------+------+---------+-------+-------+------------------------------------------+ 
| id | select_type  | table | type | possible_keys | key | key_len | ref | rows | Extra         | 
+----+--------------------+-------+------+---------------+------+---------+-------+-------+------------------------------------------+ 
| 1 | PRIMARY   | sale | ref | test   | test | 8  | const | 12466 | Using index        | 
| 2 | DEPENDENT SUBQUERY | sale | ref | test   | test | 8  | func |  3 | Using where; Using index; Using filesort | 

我明白,一個子查詢可能會很慢,但我跑出來的關於如何優化的想法。 我不確定它是否有意義,但如果我通過buyer_id進行分組,則查詢運行速度顯着加快。 因爲我依靠子查詢中的「限制1」,所以用連接代替感覺很棘手。

+0

是那個date_acquired索引降序或升序? – iiro 2013-02-18 10:19:36

+0

我可能在這裏誤解了一些東西,但是您的子查詢不會只是每次都返回您的'WHERE'子句中指定的買家ID?在這種情況下,它有什麼意義? – 2013-02-18 10:20:32

+0

'slow mysql',是不是其中的那些單詞冗餘? – 2013-02-18 10:20:35

回答

0

首先,您的查詢看起來很奇怪。除非我沒有得到你想要做的事,否則我不會理解你爲什麼要做這個子查詢,因爲你想得到「buyer_id」,但是其中buyer_id = 3585328;第二,事件如果這是一個錯字,並且你想做別的事情,如果你ORDER BY date_acquired,你應該在date_acquired上有一個索引;

+0

對不起,這是我的錯誤。我改變了子查詢來反映它的正確用法。它應該返回seller_id。 關於索引,由於mysql不能對同一個查詢使用兩個索引,是不是應該在(buyer_id,date_acquired)上有一個索引? – user2082807 2013-02-18 10:29:02

+0

你想得到什麼?給定賣家的最近買家?給定買家的最近賣家? – 2013-02-18 16:58:37

0

如果您的目的是爲了獲得最新的sid;嘗試類似:

SELECT 
    t1.buyer_id AS bid, 
    t1.date_sold AS dsold, 
    t1.id AS sid 
FROM 
    sale AS t1 
LEFT OUTER JOIN 
    sale AS t2 
    ON (t1.buyer_id = t2.buyer_id AND t1.date_acquired < t2.date_acquired) 
WHERE t2.date_acquired IS NULL;