我有一个非常具体的查询。我尝试了很多方法但是我无法达到我想要的性能。
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 5.1.44,引擎是InnoDB
答案 0 :(得分:2)
更新:根据您的评论,您需要查询中的所有列(因此您的SELECT *
)。如果是这种情况,您可以使用一些选项来最大化查询性能:
总有其他方法可以提高性能(例如,通过减少每行的大小),但主要方法是减少必须访问的行数,并增加按顺序访问而不是随机访问的行的百分比。上面的索引建议同时做到了。
下面的原始答案:
在不知道确切的架构或查询计划的情况下,此查询的主要性能问题是SELECT *
强制查找每行的聚簇索引。如果特定用户ID存在大量匹配行,并且聚簇索引的第一列不是item_user_id,那么这将是一个非常低效的操作,因为您的磁盘将尝试从teh clustered inedx中获取大量随机分布的行。
换句话说,即使过滤所需的行也很快(因为你的索引),实际上获取数据的速度较慢。
但是,如果您的聚集索引按item_user_id,item_start,item_end排序,则应该加快速度。请注意,这不是灵丹妙药,因为如果您有其他依赖于不同排序的查询,或者如果您按不同的顺序插入行,则最终可能会降低其他查询的速度。
影响较小的解决方案是创建一个覆盖索引,其中只包含您想要的列(也按item_user_id,item_start,item_end排序,然后添加您需要的其他列)。然后将您的查询更改为仅撤回所需的cols,而不是使用SELECT *
。
如果您可以发布有关DBMS品牌和版本以及表格架构的更多信息,我们可以提供更多详细信息。
答案 1 :(得分:1)
你需要SELECT *吗? 如果没有,您可以在user_id,item_start,item_end上创建索引,并在SELECT-part中将所需字段作为包含列。这一切都假设您正在使用Microsoft SQL Server 2005 +