2011-06-06 79 views
5

我有兩個表:A - 301列(第一個名爲a1 int(11)主鍵,第二個到第301個 - 雙(15,11))& B - 33列(第一個 - b1 int(11)唯一鍵,第二個 - b2 varchar(100)主鍵,...,33rd - b33 int(11)MUL)。Mysql select on indexded column slowdown on large tables

A & B有~13,500,000條記錄。

我的MySQL查詢:對於POS的每一個值,在設定的POS(1,1000,2000,...,1350),1000的倍數:

選擇A. *,B2,B5 ,b7,b8,b10,b13,b33來自a1 = b1上的A join B,其中b33> = pos和b33 < pos + 1000;

對於b33 < = 600,000的值,查詢需要1-5秒。之後,查詢開始花費20-30秒。當b33> = 8,000,000時,查詢開始以60-70s開始。我不明白爲什麼發生放緩。 b33被編入索引,並且連接發生在一個表中被定義爲主鍵且在另一個表中唯一的鍵上。有沒有解決方法?這實際上阻礙了代碼的速度,如果沒有其他作用,我將不得不將表A & B分成幾個較小的表。我真的希望我不必這樣做!請幫忙!

編輯:這裏是的O/P說明 -

** * ** * ** * ** * * 1行* ** * ** * ** * ** *
ID:1個
SELECT_TYPE:SIMPLE
表:乙
類型:範圍
possible_keys:B1,B33
鍵:B33
key_len:4
REF:NULL
行:981
額外:使用其中
* ** * ** * ** * ** * 2。行* ** * ** * ** * ** *
ID:1個
SELECT_TYPE:SIMPLE
表:一個
類型:eq_ref
possible_keys: PRIMARY
key:PRIMARY
key_len:4
ref:DBName.B.b1
行:1
附加:
2行中集(0.00秒)

+0

那麼你有一個特定的價值> 600,000的性能突然從5秒降到20秒? – 2011-06-06 06:42:54

+0

不,我更喜歡一個範圍。發佈650,000這是一場噩夢。 – ayesha129 2011-06-07 09:02:07

+0

我想這是解釋慢速輸出的輸出。而快速的?有相同的輸出嗎? – Samuel 2011-06-07 12:27:24

回答

0

我沒有MySQL的(或任何東西!)大師,但有些事情我會考慮。首先是b33均勻分佈?可能會因爲有效地檢索更多行而變慢? 其次,您是否考慮過在單個查詢中完成所有工作而不是13500?喜歡的東西:

select A.*, b2, b5, b7, b8, b10, b13, b33, (b33 - 1 DIV 1000) the_group 
from A join B on a1=b1 

第三,胡亂猜測,如果你的MySQL版本支持,使用inlinew視圖做過濾第一:

select A.*, b2, b5, b7, b8, b10, b13, b33 
from A join (select b1,b2, b5, b7, b8, b10, b13, b33 
      from B b33 >= pos and b33 < pos+1000) B_NEW 
    on a1=b1 ; 

四(應該是第一),做一次解釋計劃,並嘗試瞭解爲什麼查詢比較慢,查詢速度慢。

祝你好運!

+0

是的。 b33均勻分佈。這裏是解釋的輸出: – ayesha129 2011-06-07 09:06:18

+0

'*************************** 1. row *********** **************** ID:1個 SELECT_TYPE:SIMPLE 表:乙 類型:範圍 possible_keys:I1,ID 鍵:ID key_len:4 REF:NULL 行數:981 額外:使用位置 *************************** 2。行*************************** id:1 select_type:SIMPLE 表:a 類型:eq_ref possible_keys:PRIMARY key :PRIMARY key_len:4 ref:ja_StepUp.b.resid rows:1 Extra: set 2行(0.00 sec) ' – ayesha129 2011-06-07 09:10:48

0

在黑暗中只是一個拍...

select A.*, b2, b5, b7, b8, b10, b13, b33 
    from A join B 
    on a1=b1 
    where b33 BETWEEN pos AND pos+999; 
0

你能告訴我們,你有B設定的指標? (感興趣的是如何在B33指數的定義,以及它是否被定義在單個列或多個列):

SHOW INDEXES FROM B; 

你看到同樣的速度下降時,你只從B選擇?

select b2, b5, b7, b8, b10, b13, b33 from B where b33 >= pos and b33 < pos+1000; 

您能不能告訴我們

您正在使用的MyISAM或InnoDB的數據庫引擎(允許感興趣NULL)的部分從涉及領域B33的SHOW CREATE TABLE? (你可以在SHOW CREATE TABLE的結果中看到這個)。

0

解釋計劃和索引似乎很好。

我建議你比較配置文件,看看時間實在有云:

SET profiling=1; 

select A.*, b2, b5, b7, b8, b10, b13, b33 from A join B on a1=b1 where b33 >= 0 and b33 < 1000; 
SHOW PROFILE; 

select A.*, b2, b5, b7, b8, b10, b13, b33 from A join B on a1=b1 where b33 >= 1000000 and b33 < 1001000; 
SHOW PROFILE; 


SET profiling=0; 

,但我認爲這可能是因爲指數後600K的速度慢不適合到內存中再與更多的磁盤尋道做出

0

您需要更改此查詢!

這裏是你的舊的查詢:

select A.*, b2, b5, b7, b8, b10, b13, b33 
from A join B on a1=b1 where b33 >= pos and b33 < pos+1000; 

這裏是新的:

SELECT 
    AAA.*,b2,b5,b7,b8,b10,b13,b33 
FROM 
    A AAA INNER JOIN 
    (
     select 
      A.a1,b2,b5,b7,b8,b10,b13,b33 
     from 
      A INNER JOIN 
      (
       SELECT 
        b1,b2,b5,b7,b8,b10,b13,b33 
       FROM B 
       WHERE 
        b33 >= pos and 
        b33 < pos+1000 
      ) BB 
      ON A.a1=B.b1 
    ) BBB 
    USING (a1) 
; 

CAVEAT

這個重構查詢的目的是使查詢中的臨時表計劃儘可能小。實際上,子查詢BBB在任何給定時間應該不會超過1000行。

試試吧!

0

ayesha129p,

嘗試將b33約束移入連接子句。這聽起來像是優化器只應用b33約束前連接集創建中的一個。

select A.*, b2, b5, b7, b8, b10, b13, b33 from A join B 
    on a1=b1 and b33 >= pos and b33 < pos+1000; 

這樣優化器應該在嘗試連接之前使用b33索引並將B行設置爲1000。

1

由於您的數據庫有數百萬條記錄,您是否在做任何事情來保持您的數據庫的健康狀況?

運行以下命令夜間可能與一般的響應速度幫助,如果您的數據頻繁更改(許多刀片,也許?):

mysqlcheck --check --analyze --auto-repair --all-databases --silent

雖然我會在運行命令之前提示reading up a bit on mysqlcheck,只是讓你知道它在做什麼。

你也應該看看optimizing your InnoDB configuration,特別是innodb_buffer_pool_size(你可以給它的內存越多越好)。我在基於日期的字段(當然,我們立即索引)中遇到了類似大小的表中類似的緩慢,並且將緩衝池大小從默認的8兆字節增加到幾千兆字節,這引起了非常顯着的差異。

如果您要從聯接中涉及的任何表中刪除多行,那麼也可以考慮運行OPTIMIZE TABLE