2011-08-22 73 views
0

我有一個緩慢的查詢問題,使一個「簡單」選擇..我不明白是什麼問題...這是一個大桌子..但這是一個簡單的查詢..在大表緩慢的SQL,按時間戳過濾(int12)

的表格:

business: (1.000.000 reg) 
id (INDEX PRIMARY INT(11) UNSIGNED) 
active (INDEX TINYINT(1)) 

products: (32.000.000 reg) 
id (INDEX PRIMARY INT(11) UNSIGNED) 
business_id (INDEX INT(11) UNSIGNED) 
offer_start (INDEX INT(12) UNSIGNED) (timestam unix) 
offer_end (INDEX INT(12) UNSIGNED) (timestamp unix) 
price_offer (VARCHAR(10)) (price with decimals) 
active (INDEX TINYINT(1)) 

business.id,products.id,products.offer_start和products.offer_end被INDEX(分離)

當我做這個:

SELECT SQL_NO_CACHE * FROM products 
LEFT JOIN business ON business.id = products.business_id 
WHERE 
(business.active = '1' AND business.paylimit > 1314029906) 
AND 
(products.active = '1' AND products.offer_start < 1314029906 AND products.offer_end > 1314029906 AND products.price_offer > 0) 
LIMIT 0,10 

拿21秒。 問題是這樣的:products.offer_start < 1314029906 AND products.offer_end > 1314029906需要約20秒才能給我結果

是否可以使這個查詢過濾其他表單來加速?

+1

你能提供的解釋計劃? –

+0

你也很可能得到錯誤的答案。 WHERE(business.active ='1'AND business.paylimit> 1314029906)會將左連接更改爲內連接,因爲它必須符合該條件。 – HLGEM

+0

什麼是offer_start和offer_end的確切索引?他們是兩個單獨的索引嗎?該索引是否包含任何其他列? –

回答

2

餐桌架構的一些注意事項:

  1. offer_start(INDEX INT(12)UNSIGNED) - 12沒有任何意義,因爲INT最大的符號是11同爲OFFER_END
  2. 活躍(INDEX TINYINT(1)) - 索引是無用的,因爲1000000上的基數將是2 - 1或0
  3. price_offer(VARCHAR(10)) - 您可以使用浮點數或小數點。 products.price_offer> 0將工作得更快。
+2

從不使用浮點值進行價格計算,小數點是這裏的正確類型 – Crack

0

嘗試

SELECT SQL_NO_CACHE * FROM products 
    LEFT JOIN business ON business.id = products.business_id 
WHERE business.paylimit > 1314029906 
    AND products.offer_start < 1314029906 
    AND products.offer_end > 1314029906 
    AND products.price_offer > 0 
    AND business.active = '1' 
LIMIT 0,10 

的MySQL從左至右處理過濾器右側所以要確保這是最選擇性(返回最少行)的條件是在左邊。在條件的最左側有business.active = '1'可以使用索引,但如果它的選擇性爲50%,則該條件的其他部分並沒有使用索引。

您可能要閱讀手冊中的How MySQL Uses Indexes

編輯: 關於MySQL如何使用索引的簡短解釋:3 ways MySQL uses indexes