2009-02-03 74 views
0
SELECT i.*, i.id IN (
    SELECT id 
    FROM w 
    WHERE w.status='active') AS wish 
FROM i 
INNER JOIN r ON i.id=r.id 
WHERE r.member_id=1 && r.status='active' 
ORDER BY wish DESC 
LIMIT 0,50 

這是我試圖運行的查詢。它不能很好地擴展,我想知道這裏有人能告訴我我能在哪裏改進。我不加入到r和我,因爲我需要顯示我在w中沒有代表的行。我嘗試了左連接,但是表現不佳。這樣比較好,但並不理想。所有三張桌子都非常大。所有這三個都在我加入並選擇的字段上編制索引。需要涉及多個表的SQL查詢幫助 - 不加入選項

任何評論,指針或建設性的批評將不勝感激。

編輯加法:

我應該把它放在我原來的問題。這是SQLYog返回的EXPLAIN。

id|select_type  |table|type   |possible_keys|key  |key_len|ref |rows|Extra| 
1 |PRIMARY   |r |ref   |member_id,id |member_id|3  |const|3120|Using where; Using temporary; Using filesort 
1 |PRIMARY   |i |eq_ref  |id   |id  |8  |r.id |1 | 
2 |DEPENDENT SUBQUERY|w |index_subquery|id,status |id  |8  |func |8 |Using where 


編輯樂dorfier - 更多評論...

我應該指出,用W鍵是(member_id,ID)。所以每個id可以在w中存在多次,我只想知道它是否存在。

+0

-1用於請求優化幫助而不發佈表的DDL或查詢的EXPLAIN計劃。 – 2009-02-03 23:24:37

回答

3

WHERE x IN()相同的INNER JOINSELECT DISTINCT子查詢,並且在一般情況下,一個連接到一個子查詢將通常有更好的表現,如果優化不轉INJOIN - 這是它應該:

SELECT i.* 
FROM i 
INNER JOIN (
    SELECT DISTINCT id 
    FROM w 
    WHERE w.status = 'active' 
) AS wish 
    ON i.id = wish.id 
INNER JOIN r 
    ON i.id = r.id 
WHERE r.member_id = 1 && r.status = 'active' 
ORDER BY wish.id DESC 
LIMIT 0,50 

其中,大概相當於這個,如果你不需要DISTINCT

SELECT i.* 
FROM i 
INNER JOIN w 
    ON w.status = 'active' 
    AND i.id = wish.id 
INNER JOIN r 
    ON i.id = r.id 
    AND r.member_id = 1 && r.status = 'active' 
ORDER BY i.id DESC 
LIMIT 0,50 

請張貼您的架構。

如果您正在使用的願望作爲存在標誌時,嘗試:

SELECT i.*, CASE WHEN w.id IS NOT NULL THEN 1 ELSE 0 END AS wish 
FROM i 
INNER JOIN r 
    ON i.id = r.id 
    AND r.member_id = 1 && r.status = 'active' 
LEFT JOIN w 
    ON w.status = 'active' 
    AND i.id = w.id 
ORDER BY wish DESC 
LIMIT 0,50 

您可以使用相同的技術與LEFT JOINSELECT DISTINCT子查詢。我假設你沒有指定w.member_id,因爲你想知道是否有成員有此?在這種情況下,一定要使用SELECT DISTINCT。你應該有id作爲w第一列的索引,以及爲了使這種執行:

SELECT i.*, CASE WHEN w.id IS NOT NULL THEN 1 ELSE 0 END AS wish 
FROM i 
INNER JOIN r 
    ON i.id = r.id 
    AND r.member_id = 1 && r.status = 'active' 
LEFT JOIN (
    SELECT DISTINCT w.id 
    FROM w 
    WHERE w.status = 'active' 
) AS w 
    ON i.id = w.id 
ORDER BY wish DESC 
LIMIT 0,50 
1

請發佈EXPLAIN列表。並解釋表和列的含義。

希望似乎是一個布爾值 - 而你是通過它來命令?


編輯:好吧,它看起來像它正在做它被指示要做的事情。凱德似乎在廣泛地思考這可能意味着什麼(他可能只是爲了努力而投票)。但我真的寧願你告訴我們。

野生猜測只是混淆每個人(包括你,我敢肯定。)


OK,基於新的信息,這是我(略少野)的猜測。

SELECT i.*, 
    CASE WHEN EXISTS (SELECT 1 FROM w WHERE id = i.id AND w.status = 'active' THEN 1 ELSE 0 END) AS wish 
FROM i 
INNER JOIN r ON i.id = r.id AND r.status = 'active' 
WHERE r.member_id = 1 

你想在w中的每個匹配行?或者只是爲了知道i.id,是否存在有效的w記錄?我假設第二個答案,所以你不需要訂單 - 無論如何它只有一個ID。而且由於你只是從我那裏返回列,如果r中有多行,你只會得到重複的行。

如何發佈您期望得到正確答案的內容?

0

你試過嗎?

SELECT i.*, w.id as wish FROM i 
LEFT OUTER JOIN w ON i.id = w.id 
    AND w.status = 'active' 
WHERE i.id in (SELECT id FROM r WHERE r.member_id = 1 AND r.status = 'active') 
ORDER BY wish DESC 
LIMIT 0,50 
+0

它似乎比較慢。我應該提到w的關鍵是(member_id,id)。所以每個id可以在w中存在多次,我只想知道它是否存在。 – 2009-02-03 23:38:04

+0

這是否意味着您可以將w.member_id = 1添加到ON子句中? – jmucchiello 2009-02-04 01:38:42

1

我應該把它放在我原來的問題。這是SQLYog返回的EXPLAIN。
id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
1 | PRIMARY | r | ref | member_id,id | member_id | 3 | const | 3120 |使用where;使用臨時;使用filesort
1 | PRIMARY | i | eq_ref | id | id | 8 | r。ID | 1 |
2 | DEPENDENT SUBQUERY | W | index_subquery | ID,狀態| ID | 8 | FUNC | 8 |使用其中

+0

這應該是問題的一部分,不作爲答案發布。 – 2009-02-03 23:40:06

+0

如果你只有33個代表,你就不那麼容易做到了。 – dkretz 2009-02-03 23:43:22

1
... 
ORDER BY wish DESC 
LIMIT 0,50 

這似乎是很大的開支。您正在按計算列「wish」進行排序,該列不能從索引中受益。這迫使它使用一個文件夾(如EXPLAIN所示)輸出,這意味着它將整個結果集寫入磁盤並使用非常緩慢的磁盤I/O進行排序。

當你發佈這樣的問題時,你不應該期待別人猜測你是如何定義表和索引的。獲取完整定義非常簡單:

mysql> SHOW CREATE TABLE w; 
mysql> SHOW CREATE TABLE i; 
mysql> SHOW CREATE TABLE r; 

然後將輸出粘貼到您的問題中。

目前尚不清楚「wish」列的目的是什麼。 「IN」謂詞是一個布爾表達式,所以它總是以0或1結果。但是我猜你試圖使用「IN」來希望在不進行連接的情況下完成連接。如果你描述你想要完成的事情,這將有所幫助。

試試這個:

SELECT i.* 
FROM i 
INNER JOIN r ON i.id=r.id 
LEFT OUTER JOIN w ON i.id=w.id AND w.status='active' 
WHERE r.member_id=1 AND r.status='active' 
AND w.id IS NULL 
LIMIT 0,50; 

它使用一個額外的外部聯接,但它根據我與EXPLAIN測試不招致文件排序。