2011-06-08 117 views
0

我必須遵循表:MySQL的:嵌套查詢速度問題

|ELEMENTS| 
------------ 
|id_element| 
|id_catalog| 
|value| 


|CATALOG| 
------------ 
|id_catalog| 
|catalog_name| 
|show| 
|status| 

我嘗試添加不同indecies(幾個變種):

1) ELEMENT: pair(id_element, id_catalog) and id_element and id_catalog 
2) ELEMENT: pair(id_element, id_catalog) and id_element 
3) ELEMENT: pair(id_element, id_catalog) and id_catalog 
4) ELEMENT: id_element and id_catalog 

1) CATALOG: pair(show, status) and id_catalog 
2) CATALOG: id_catalog and show and status 

執行跟隨選擇:

SELECT DISTINCT `id_element` FROM `ELEMENTS` 
     WHERE (id_catalog IN (SELECT `id_catalog` FROM `CATALOG` WHERE status=1 AND show = 1)) limit 10 

如果有一些行,那麼它的工作速度非常快。但如果它是空的 - 需要4秒以上。

同時「SELECT id_catalog FROM CATALOG WHERE status=1 AND show = 1」工作快,既有一些行和空。

在表格元素有100.000記錄 在表類別有15.000記錄

我也試圖「加入」,但它需要更多的時間比以前。

爲什麼空查詢的工作時間如此長,以及我應該如何提高速度?

這裏有解釋的答案:

id | select_type   | table     | type    | possible_keys    | key  | key_len | ref | rows | Extra 
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
1 | 'PRIMARY',   |'ELEMENTS'    | 'index'   | ''      | null  | null | null | 270044 | 'Using where; Using temporary' 
2 | 'DEPENDENT SUBQUERY' | 'CATALOG'    | 'unique_subquery' | 'PRIMARY,pair,id_catalog' | 'PRIMARY' | '4'  | 'func' | 1  | 'Using where' 

回答

1

那麼,你遇到問題的原因是,你要爲每個請求提取整個目錄數據庫,並找到元素和目錄之間的每個匹配項。如果MySQL發現10個條目,它會保留,但如果它從未發現它們,它將繼續檢查整個數據庫。我會使用EXISTS查詢嘗試並獲得一些性能提升。

SELECT DISTINCT(e.id_element) 
FROM ELEMENTS e 
WHERE EXISTS (
    SELECT * 
    FROM CATALOG c 
    WHERE c.id_catalog = e.id_catalog 
    AND c.status = 1 
    AND c.show = 1) 
LIMIT 10; 

這將減少的時間MySQL的花費可以由內層查詢徵收LIMIT 1尋找目錄每個元素的量,但你總是運行的搜索時間長的風險時,有可能不匹配。

2

我猜索引CATALOG(status,show)將允許一個快速的答案給分選。

然後ELEMENTS(id_catalog)上的一些索引將加快主要問題的答案。

也許這取決於這些列的統計數據:它們沒有足夠的選擇性,無論如何你最終會得到很多行。

使用上述兩個索引時,您能否顯示EXPLAIN的輸出?

+0

Thx,我在上面添加了問題答案。 – Anthony 2011-06-08 06:00:25

1

我會把這些指標有:

CREATE INDEX idx_element_1 ON ELEMENT (id_catalog); 
CREATE INDEX idx_catalog_1 ON CATALOG (status, show); 

而且這些,雖然他們可能沒有查詢所需要的(這大概應該是主鍵,除非你有重複):

CREATE INDEX idx_element_2 ON ELEMENT (id_element); 
CREATE INDEX idx_catalog_2 ON CATALOG (id_catalog); 

您可以刪除其他索引並創建這些索引並查看查詢結果嗎?

+0

在這種情況下,工作時間比以前更長,甚至有一些行:( 順便說一下,ELEMENT不使用任何索引。 – Anthony 2011-06-08 06:07:11

+0

@Anthony你是什麼意思,ELEMENT不使用任何索引?如果你有一個因爲它是WHERE子句的一部分,所以它應該使用它 – deltaforce2 2011-06-08 06:11:05

+0

它是空的,我將在以後再試一次,只是想試試Kyle寫的 – Anthony 2011-06-08 06:21:02

2

爲什麼不簡單地寫一個連接來幫助優化器完成它的工作?

SELECT DISTINCT id_element 
FROM elements JOIN catalog ON elements.id_catalog=catalog.id_catalog 
WHERE status=1 AND show = 1 
LIMIT 10 

(未測試的)

-1

Thx至所有。我通過表格非規範化來解決它。因爲這些分離的數據中有太多的數據。 我決定將它合併到一張桌子上。現在它完美。現在查詢總是需要0.03秒。

+1

所以你通過非規範化修復了一個查詢,並且你銷燬了其他查詢從正常化中受益的過程,這是一個不好的交易。 – 2011-07-26 20:02:38