MySQL查询需要优化

pla*_*men 0 mysql optimization

我收到了这个问题:

SELECT user_id  
FROM basic_info  
WHERE age BETWEEN 18 AND 22 AND gender = 0  
ORDER BY rating  
LIMIT 50  
Run Code Online (Sandbox Code Playgroud)

该表看起来像(它包含大约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;  
Run Code Online (Sandbox Code Playgroud)

查询本身已经过优化,但它必须走大约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  
Run Code Online (Sandbox Code Playgroud)

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

谢谢 !

int*_*tgr 7

有两个有用的索引可以帮助这个查询:

KEY gender_age (gender, age)- 该指数既可以满足gender=0条件,也可以满足age BETWEEN 18 AND 22.但是,因为你有一个范围的条件下在age现场,加入了rating列索引不会放弃排序的结果-因此,MySQL会选择所有匹配的行-忽略你的极限条款-做一个额外的文件排序不分.

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个条目,而不是更多.