2011-10-05 93 views
1

好的,我有一個查詢,我似乎無法得到優化。也許我在MySQL中做得太多了,應該更多地委託給PHP。這樣的查詢需要一分鐘左右,但我真的需要它比這更快。下面是一個假設的結構,應該讓你知道我正在努力完成什麼。查詢性能問題。我可以優化這個嗎?

您會注意到我正在向PHP變量$ bookList提供查詢,該變量包含當前用戶擁有的book_id列表,格式爲逗號分隔格式。

對於這個例子,假設用戶有70個book_id被分配給他的圖書館($ bookList),他想知道哪些商店與他的圖書館共享最多的圖書。每家商店有70本書,但有20多萬商店。少於50%的商店將被過濾掉。

表1:my_books

id: mediumint 
book_id: smallint 

表2:store_books

store_id: mediumint 
book_id: smallint 
index: store_id 
index: book_id 

表3;商店

id: mediumint 
name: varchar(50) 
primary: id 

查詢:

SELECT count(s.book_id) AS commonBooks, s.id 
       FROM store_books AS sb 
       INNER JOIN stores AS s ON s.id = sb.id 
       WHERE sb.book_id IN ($bookList) 
       GROUP BY sb.store_id 
       HAVING commonBooks > 35 
       ORDER BY commonBooks 

提前感謝!

+2

你的意思是sb.id在內部連接上是sb.store_id嗎? –

+1

我認爲你需要一個表'store_books'中的複合索引。 on'(store_id,book_id)' –

+1

您還應該用'count(*)'替換'count(s.book_id)'' –

回答

2

借鑑@Joe Stefanelli的回答,使用臨時表。
確保您有bl.book_id

主索引BTW:你似乎在你的查詢時出現錯誤:

SELECT count(*) AS commonBooks, s.id 
FROM store_books AS sb 
INNER JOIN stores AS s ON s.id = sb.store_id -- <<sb.store_id, not sb.id 
WHERE sb.book_id IN (SELECT bl.book_id FROM tempBookList) 
GROUP BY sb.store_id 
HAVING commonBooks > 35 
ORDER BY commonBooks DESC 

這是一個鮮爲人知的事實是,MySQL只能使用一個索引每(次)選擇。
確保在表store_book
count(*)有一個綜合指數(有時)快於count(afield)(永不慢)

Table 2: store_books 

store_id: mediumint 
book_id: smallint 
index: (store_id, book_id) <<-- composite primary index. 
index: (book_id) 

這個查詢將在InnoDB的不是MyISAM數據運行得更快因爲InnoDB可以使用覆蓋索引來解決此查詢,並且不需要讀取實際表中的數據。

+0

有任何理由,綜合指數不應該是主要的?我目前正在將整個項目移植到只應使用INNODB的Symfony上。希望這將有助於你的建議。 – IOInterrupt

+0

@IOInterrupt,o反轉複合索引**必須**爲主。 – Johan

+0

只是想放下並說謝謝。首先感謝您真正解釋您的建議,這比僅僅說「做這個」沒有任何解釋爲什麼要這樣做更有幫助。 – IOInterrupt

1

就我個人而言,我會將$ bookList中的值提取到臨時表中,並用臨時表中的JOIN替換IN。

SELECT count(s.book_id) AS commonBooks, s.id 
       FROM store_books AS sb 
       INNER JOIN stores AS s ON s.id = sb.id 
       INNER JOIN tempBookList AS bl ON sb.book_id = bl.book_id 
       GROUP BY sb.store_id 
       HAVING commonBooks > 35 
       ORDER BY commonBooks 
+0

那麼my_books確實有這些ID的。你認爲加入這張桌子會更快,而不是使用IN? – IOInterrupt

+0

@IOInterrupt我這樣做。這當然值得嘗試。 –