免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 7416 | 回复: 8
打印 上一主题 下一主题

Datetime类型字段上的索引和记录条数有关吗? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-04-20 18:31 |只看该作者 |倒序浏览
report 表索引字段 calldate(datetime)

查询1:
explain SELECT * FROM report WHERE calldate >= '2009-04-09 00:00:00';

+----+-------------+----------+------+---------------+------+---------+------+--------+-------------+
| id | select_type | table    | type | possible_keys | key  | key_len | ref  | rows   | Extra       |
+----+-------------+----------+------+---------------+------+---------+------+--------+-------------+
|  1 | SIMPLE      | report  | ALL  | calldate      | NULL | NULL    | NULL | 128305 | Using where |
+----+-------------+----------+------+---------------+------+---------+------+--------+-------------+
1 row in set (0.00 sec)

查询2:
explain SELECT * FROM report  WHERE calldate >= '2009-04-10 00:00:00';

+----+-------------+----------+-------+---------------+----------+---------+------+-------+-------------+
| id | select_type | table    | type  | possible_keys | key      | key_len | ref  | rows  | Extra       |
+----+-------------+----------+-------+---------------+----------+---------+------+-------+-------------+
|  1 | SIMPLE      | report  | range | calldate      | calldate | 8       | NULL | 23029 | Using where |
+----+-------------+----------+-------+---------------+----------+---------+------+-------+-------------+
1 row in set (0.00 sec)


为什么两个时间字段的范围不一样就导致了索引的使用

论坛徽章:
0
2 [报告]
发表于 2009-04-20 18:34 |只看该作者
呃,这正是mysql聪明的地方,不排除小聪明的可能

论坛徽章:
0
3 [报告]
发表于 2009-04-20 20:48 |只看该作者
我把2008-04-09以前的数据删除,发现记录在2009-04-17是个界限,这个真的头一次碰到很郁闷的事。。

论坛徽章:
9
每日论坛发贴之星
日期:2016-01-04 06:20:00数据库技术版块每日发帖之星
日期:2016-01-04 06:20:00每日论坛发贴之星
日期:2016-01-04 06:20:00数据库技术版块每日发帖之星
日期:2016-01-04 06:20:00IT运维版块每日发帖之星
日期:2016-01-04 06:20:00IT运维版块每日发帖之星
日期:2016-01-04 06:20:00综合交流区版块每日发帖之星
日期:2016-01-04 06:20:00综合交流区版块每日发帖之星
日期:2016-01-04 06:20:00数据库技术版块每周发帖之星
日期:2016-03-07 16:30:25
4 [报告]
发表于 2009-04-21 11:55 |只看该作者
此时mysql优化器认为整表的读取更优,所以没有使用索引。
你可以使用
SELECT * FROM report  use index(calldate) WHERE calldate >= '2009-04-10 00:00:00';
来强制使用索引

论坛徽章:
0
5 [报告]
发表于 2009-04-21 17:35 |只看该作者
谢楼上!

论坛徽章:
0
6 [报告]
发表于 2010-09-08 09:21 |只看该作者
此时mysql优化器认为整表的读取更优,所以没有使用索引。
你可以使用
SELECT * FROM report  use index( ...
cenalulu 发表于 2009-04-21 11:55



    同问, 难道我们在程序中也要写类似这样的SQL吗?  
我感觉这样实在不太合适。。 请问各位大大怎么处理这样的问题?

论坛徽章:
0
7 [报告]
发表于 2010-09-08 09:26 |只看该作者
取数据的语句:

SELECT * FROM my_table WHERE created_at < '2010-01-20';

用 EXPLAIN 检查,发现 type 是 ALL, key 是 NULL,根本没用上索引。

可以确定的是,created_at 字段设定索引了。

什么原因呢?

用 SELECT COUNT(*) 看了一下符合 WHERE 条件的记录总数,居然是 6W 多条!!

难怪不用索引,这时用索引毫无意义,就好像 10 万条记录的用户表,有个性别字段,不是男就是女,在这种字段设置索引是错误的决定。

稍微改造一下上述语句:

SELECT * FROM my_table WHERE created_at BETWEEN '2009-12-06' AND '2010-01-20';

这回问题解决!



符合条件的记录只有几百条,EXPLAIN 的 type 是 range,key 是 created_at,Extra 是 Using where 。

自己总结个准则,索引的目的就是尽量缩小结果集,这样才能做到快速查询。

论坛徽章:
0
8 [报告]
发表于 2010-09-08 09:27 |只看该作者
6万条记录符合条件,已经超出总记录数的一半,这时索引已经没有意义了,因此 MySQL 放弃使用索引。

这与设置 gender 字段,并加上索引的情况相似,当你要把所有男性记录都选取出来,符合条件的记录数约占总数的一半,MySQL 同样不会使用这个索引。

唯一值越多的字段,使用索引的效果越好。

设置联合索引时,唯一值越多的,越应该放在“左侧”。




希望对其他搜索到此贴的同问题关注者带来些帮助!

论坛徽章:
9
每日论坛发贴之星
日期:2016-01-04 06:20:00数据库技术版块每日发帖之星
日期:2016-01-04 06:20:00每日论坛发贴之星
日期:2016-01-04 06:20:00数据库技术版块每日发帖之星
日期:2016-01-04 06:20:00IT运维版块每日发帖之星
日期:2016-01-04 06:20:00IT运维版块每日发帖之星
日期:2016-01-04 06:20:00综合交流区版块每日发帖之星
日期:2016-01-04 06:20:00综合交流区版块每日发帖之星
日期:2016-01-04 06:20:00数据库技术版块每周发帖之星
日期:2016-03-07 16:30:25
9 [报告]
发表于 2010-09-08 12:49 |只看该作者
关键还是索引要建的恰到好处
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP