2010-07-31 156 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