免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2423 | 回复: 5

这种查询为啥没用到索引 [复制链接]

论坛徽章:
0
发表于 2012-03-21 16:04 |显示全部楼层
表1,用户表
  1. CREATE TABLE `all_users` (
  2.   `user_id` varchar(64) NOT NULL comment "用户id",
  3.   `age` int(11) default NULL "用户年龄",
  4.   PRIMARY KEY  (`user_id`)
  5. ) ENGINE=MyISAM DEFAULT CHARSET=utf8
复制代码
表2 用户登陆表
  1. CREATE TABLE `active_logs` (
  2.   `user_id` varchar(64) NOT NULL,
  3.   `user_ip` varchar(15) NOT NULL,
  4.   `time` datetime NOT NULL,
  5.   `log_date` int(11) NOT NULL,
  6.   `log_hour` tinyint(4) NOT NULL,
  7.   UNIQUE KEY `user_id` (`user_id`,`time`),
  8.   KEY `log_date` (`log_date`),
  9.   KEY `log_hour` (`log_hour`)
  10. ) ENGINE=InnoDB DEFAULT CHARSET=utf8
复制代码
select count(*) from all_users;
+----------+
| count(*) |
+----------+
|     7844 |
+----------+
select count(*) from active_logs;
+----------+
| count(*) |
+----------+
|  1314828 |
+----------+



需要统计在某一段时间内登陆的用户
  1. SELECT count(user_id) AS num,age FROM all_users WHERE user_id IN (SELECT distinct user_id FROM active_logs WHERE log_date>=20120315 AND log_date<=20120315) GROUP BY age
复制代码
explain出来的结果:
  1. explain SELECT count(user_id) AS num,age FROM all_users WHERE user_id IN (SELECT distinct user_id FROM active_logs WHERE log_date>=20120315 AND log_date<=20120315) GROUP BY age
复制代码
  1. +----+--------------------+------------------+-------+------------------+----------+---------+------+------+----------------------------------------------+
  2. | id | select_type        | table            | type  | possible_keys    | key      | key_len | ref  | rows | Extra                                        |
  3. +----+--------------------+------------------+-------+------------------+----------+---------+------+------+----------------------------------------------+
  4. |  1 | PRIMARY            | all_users        | ALL   | NULL             | NULL     | NULL    | NULL | 7844 | Using where; Using temporary; Using filesort |
  5. |  2 | DEPENDENT SUBQUERY | stat_active_logs | range | user_id,log_date | log_date | 4       | NULL |    1 | Using where; Using index; Using temporary    |
  6. +----+--------------------+------------------+-------+------------------+----------+---------+------+------+----------------------------------------------+
复制代码
对于all_users做了全表扫描,会不会由于子查询里查出的user_id会很多,但大部分不会超过all_users里的 10%,所以应该可以用索引,还是由于user_id为varchar类型的原因,如果用user_id IN('11111111','113131313')这样的就会用到主键索引

论坛徽章:
0
发表于 2012-03-21 16:57 |显示全部楼层
修改一下试试呢:

select count(all_users.user_id) as num, age from active_logs  left join all_users on all_users.user_id=active_logs.user_id where log_date>=20120315 AND log_date<=20120315 GROUP BY age;

mysql> explain select count(all_users.user_id) as num, age from active_logs  left join all_users on all_users.user_id=active_logs.user_id where log_date>=20120315 AND log_date<=20120315 GROUP BY age;
+----+-------------+-------------+--------+---------------+----------+---------+--------------------------+------+-----------------------------------------------------------+
| id | select_type | table       | type   | possible_keys | key      | key_len | ref                      | rows | Extra                                                     |
+----+-------------+-------------+--------+---------------+----------+---------+--------------------------+------+-----------------------------------------------------------+
|  1 | SIMPLE      | active_logs | index  | log_date      | log_date | 4       | NULL                     |    1 | Using where; Using index; Using temporary; Using filesort |
|  1 | SIMPLE      | all_users   | eq_ref | PRIMARY       | PRIMARY  | 194     | test.active_logs.user_id |    1 |                                                           |
+----+-------------+-------------+--------+---------------+----------+---------+--------------------------+------+-----------------------------------------------------------+


1,用子查询性能不是很好,
2,没有用primary key的原因应该就是你所说的那样,以前好像有人讨论过9%左右吧,这个比例难说,由mysql来权衡,10%的随机读,可能还不如ALL的顺序读。

论坛徽章:
0
发表于 2012-03-21 20:55 |显示全部楼层
回复 2# RogerZhuo


    成功了,多谢,

论坛徽章:
0
发表于 2012-03-21 22:38 |显示全部楼层
回复 3# starzhestarzhe
不客气,
第一个用了覆盖索引,第二个用了主键,如果满足你的需求,这个查询应该速度会提高 很多。

   

论坛徽章:
0
发表于 2012-04-18 17:44 |显示全部楼层
学习了,where in  子查询 效率会很差,用exists 或者join 替换

论坛徽章:
0
发表于 2012-04-19 21:55 |显示全部楼层
回复 2# RogerZhuo


    为什么要left join? LZ的原意不是这样的吧。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP