2009-02-10 39 views
4

考慮由多個表的視圖...例如,其由表car的接合到bodyenginewheelsstereo和。它可能是這個樣子:Optmizing MySQL的GROUP BY或DISTINCT上大的觀點

v_active_cars視圖

SELECT * FROM car 
    INNER JOIN body ON car.body = body.body_id 
    INNER JOIN engine ON car.engine = engine.engine_id 
    INNER JOIN wheels ON car.wheels = wheels.wheels_id 
    INNER JOIN stereo ON car.stereo = stereo.stereo_id 
    WHERE car.active = 1 
    AND engine.active = 1 
    AND wheels.active = 1 
    AND stereo.active = 1 

汽車的每個組件都有一個「活動」標誌。 現在,我需要找到所有在現用汽車中可用的立體聲。 要做到這一點需要使用整個視圖,而不僅僅是stereo表 - 只是因爲立體聲是活動的並不意味着它可以在汽車中使用。

所以我可以做

SELECT DISTINCT stereo_id FROM v_active_cars 

即使這可能會返回一個非常小的行數,它還是老樣子一個非常緩慢的查詢。

我已經試過這一點,但它更慢:

SELECT stereo_id FROM stereo WHERE EXISTS 
(SELECT 1 FROM v_active_cars WHERE stereo_id = stereo.stereo_id) 

還有什麼我能做的,使這個更快?

+0

請發佈每個表有多少行以及查詢需要多長時間。 – Quassnoi 2009-02-10 17:13:39

+0

你好,關於每張桌子上的號碼有一些主動和非主動的想法,以及你從視圖中得到的號碼。如果它的成千上萬秒的時間,那麼這可能是所有你可以期望的,如果它的數百並且需要幾分鐘,那麼在某處可能有些問題 – 2009-02-10 17:19:39

回答

1
  1. 確保有索引所有的JOIN你的情況
    • ,每個級別由密鑰和標記選擇兩者。將該標誌添加爲索引的一部分可能允許DB僅使用索引,而不是讀取整個記錄
    • 確保您有足夠的RAM來容納結果集。特別是InnoDB表格有很多你必須調整的旋鈕。大多數默認設置假設非常舊硬件和RAM太少。
1

你似乎在做一切正確。下一步將是檢查指數的覆蓋面。

+0

索引看起來很好,不幸的是:/ – Greg 2009-02-10 17:05:12

0

試試這個:

SELECT stereo_id 
FROM stereo s, (
    SELECT * 
    FROM v_active_cars 
    ORDER BY stereo_id 
) v 
WHERE s.active = 1 
    AND v.stereo = s.stereo_id 

ORDER BY這裏應防止謂語推入視圖,優化程序選擇散列連接。

0

您可以嘗試爲每個只顯示活動部分的部分創建視圖,然後加入到這些部分。例如。

VIEW activeCar 
SELECT * FROM car WHERE car.active = 1 

VIEW activeEngine 
SELECT * FROM engine WHERE engine.active = 1 

那麼你最終視圖可以

SELECT * FROM activeCar 
INNER JOIN activeEngine ON activeCar.engine = activeEngine.engine_id 

顯然,要確保你有在活動列的索引。

另一種替代方法是在ID和活動標誌上都有一個索引。加入後,您可以執行active = 1。這樣,只有一個索引用於連接,而不是一個用於連接,另一個用於連接。

SELECT * FROM car 
INNER JOIN body ON car.body = body.body_id AND body.active = 1 
INNER JOIN engine ON car.engine = engine.engine_id AND engine.active = 1 
INNER JOIN wheels ON car.wheels = wheels.wheels_id AND wheels.active = 1 
INNER JOIN stereo ON car.stereo = stereo.stereo_id AND stereo.active = 1