MySQL查询需要优化

时间:2009-11-17 09:22:55

标签: mysql optimization

我收到了这个问题:

SELECT user_id  
FROM basic_info  
WHERE age BETWEEN 18 AND 22 AND gender = 0  
ORDER BY rating  
LIMIT 50  

该表看起来像(并且它包含大约700k行):

CREATE TABLE IF NOT EXISTS `basic_info` (  
  `user_id` mediumint(8) unsigned NOT NULL auto_increment,  
  `gender` tinyint(1) unsigned NOT NULL default '0',  
  `age` tinyint(2) unsigned NOT NULL default '0',  
  `rating` smallint(5) unsigned NOT NULL default '0',  
  PRIMARY KEY  (`user_id`),  
  KEY `tmp` (`gender`,`rating`),  
) ENGINE=MyISAM;  

查询本身已经过优化,但它必须走大约20万行来完成他的工作。 这是解释输出:

id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra  
1   SIMPLE  basic_info  ref     tmp,age     tmp     1   const   200451  Using where  

是否可以优化查询,使其不会超过200k行?

谢谢!

3 个答案:

答案 0 :(得分:7)

有两个有用的索引可以帮助您进行此查询:

KEY gender_age (gender, age) - 此索引既可以满足gender=0条件,也可以满足age BETWEEN 18 AND 22。但是,因为age字段上有范围条件,所以将rating列添加到索引中将不会给出排序结果 - 因此MySQL将选择所有匹配的行 - - 忽略你的LIMIT条款 - 并且无论如何都要做一个额外的 filesort

KEY gender_rating (gender, rating) - 您已有的索引;此索引可以满足gender=0条件,并按rating检索已经排序的数据 。但是,数据库必须使用gender=0扫描所有元素,并消除那些不在范围内的人age BETWEEN 18 AND 22

更改架构

如果上述内容对您没有帮助,则始终可以更改架构。一种这样的方法是通过定义年龄组列将age BETWEEN条件转换为相等条件;例如,0-12岁的年龄组为1岁,12-18岁的年龄组为2岁等。

这样,索引为(gender, agegroup, rating)且查询为WHERE gender=0 AND agegroup=3 ORDER BY rating将从索引中检索所有结果并已排序。在这种情况下,LIMIT子句应从表中获取50个条目,而不再是。

答案 1 :(得分:1)

扩展您tmp - 键以包含age - 列:

KEY `tmp` (`age`,`gender`,`rating`)

答案 2 :(得分:1)

尝试使用InnoDB来提高性能?

基准here