2010-07-31 153 views
0

我有一個非常具體的查詢。我嘗試了很多方法,但是我無法達到我想要的表現。如何優化此查詢?

SELECT * 
FROM 
    items 
WHERE 
    user_id=1 
AND 
    (item_start < 20000 AND item_end > 30000) 

我創建和user_ID的指數,item_start,item_end

這個沒有工作,我放棄了所有的索引和創建新的索引

USER_ID,(item_start,item_end)

這也沒有奏效。

(USER_ID,item_start和item_end是INT)

編輯:數據庫爲MySQL 44年1月5日,引擎InnoDB的

+0

你看過查詢的查詢計劃,檢查它是否使用索引? – 2010-07-31 21:33:07

+0

什麼數據庫系統和什麼版本? – 2010-07-31 21:38:36

+0

首先:刪除'SELECT *'並使用'SELECT field1,field2,field3'方法 – 2010-07-31 21:39:05

回答

1

你需要SELECT *? 如果不是,您可以在user_id,item_start,item_end上創建一個索引,並在SELECT部分​​中包含所需的字段作爲包含列。這一切都假設你正在使用Microsoft SQL Server 2005+

+0

我需要所有字段,也許我可以將表格分成兩張表格(第二張表格涵蓋了文本和其他大字段),但我不想因爲某些特定原因執行此操作。 – jsonx 2010-07-31 22:11:26

2

更新:根據您的評論下面,你需要在查詢中的所有列(因此你的SELECT *)。如果是這樣的話,你有幾個選項,以最大限度地提高查詢性能:

  1. 創建(或變更)您的聚集索引上item_user_id,item_start,item_end。這將確保爲每個查詢檢查儘可能少的行。根據我下面的原始答案,這種方法可能會加速這個特定的查詢,但可能會減慢其他查詢,所以您需要小心。
  2. 如果更改聚簇索引不切實際,則可以在item_user_id,item_start,item_end和您的查詢需要的任何其他列上創建非聚簇索引。這會稍微降低插入速度,並且會增加表格所需的存儲空間,但會加快此特定查詢的速度。

總是有其他方法來提高性能(例如通過減少每行的大小),但主要方法是減少必須訪問的行數並增加順序訪問的行的百分比而不是隨機的。上面的索引建議都可以。

ORIGINAL回答以下:

不知道確切的模式或查詢計劃,該查詢的主要性能問題是SELECT *強制查詢返回的每一行的聚集索引。如果特定用戶標識的匹配行數很大,並且聚簇索引的第一列不是item_user_id,那麼這可能是一個非常低效的操作,因爲您的磁盤將試圖從聚簇的子集中獲取大量隨機分佈的行。

換句話說,即使你想過濾所需的行速度很快(因爲你的索引),但實際獲取數據的速度較慢。 。

但是,如果您的聚簇索引是按item_user_id,item_start,item_end排序的,那麼應該加快速度。請注意,這不是萬能的,因爲如果您有其他查詢依賴於不同的順序,或者如果您以不同順序插入行,最終可能會減慢其他查詢的速度。

影響較小的解決方案是創建一個只包含您想要的列的覆蓋索引(也可以按item_user_id,item_start,item_end排序,然後添加您需要的其他列)。 THen將您的查詢更改爲只回拉所需的色譜柱,而不是使用SELECT *

如果您可以發佈有關DBMS品牌和版本以及表格架構的更多信息,並且我們可以提供更多詳細信息。

+0

我用EXPLAIN與「SELECT *」和「SELECT id」查看每個查詢約16500行。索引在兩者之間效果很好,但這是不同的。 – jsonx 2010-07-31 22:15:40