mysql数据库索引查询优化的分享

架构研究室 2008年08月11日 20:21 查看3180次 作者: Michael Field  【
文章分类:数据库技术

问题描述:


我们要访问的表是一个非常大的表,四千万条记录,id是主键,program_id上建了索引。
执行一条SQL:

select * from program_access_log where program_id between 1 and 4000

这条SQL非常慢。
我们原以为处理记录太多的原因,所以加了id限制,一次只读五十万条记录

select * from program_access_log where id between 1 and 500000 and program_id between 1 and 4000

但是这条SQL仍然很慢,速度比上面一条几乎没有提升。
Mysql处理50万条记录的表,条件字段还建了索引,这条语句应该是瞬间完成的。


问题分析:


这张表大约容量30G,数据库服务器内存16G,无法一次载入。就是这个造成了问题。
这条SQL有两个条件,ID一到五十万和Program_id一到四千,因为program_id范围小得多,mysql选择它做为主要索引。
先通过索引文件找出了所有program_id在1到4000范围里所有的id,这个过程非常快。
接下来要通过这些id找出表里的记录,由于这些id是离散的,所以mysql对这个表的访问不是顺序读取。
而这个表又非常大,无法一次装入内存,所以每访问一条记录mysql都要重新在磁盘上定位并把附近的记录都载入内存,大量的IO操作导致了速度的下降。

问题解决方案:
1. 以program_id为条件对表进行分区
2. 分表处理,每张表的大小不超过内存的大小
然而,服务器用的是mysql5.0,不支持分区,而且这个表是公共表,无法在不影响其它项目的条件下修改表的结构。
所以我们采取了第三种办法:

select * from program_access_log where id between 1 and 500000 and program_id between 1 and 15000000

现在program_id的范围远大于id的范围,id被当做主要索引进行查找,由于id是主键,所以查找的是连续50万条记录,速度和访问一个50万条记录的表基本一样

总结:
这是一个在千万笔记录表中由于使用了索引导致了数据查找变慢的问题,有一定的典型性和大家交流下!

责任编辑:抽烟的蚊子

给文章打个分先...

平均分:1.2(134 次)

-5 -4 -3 -2 -1 0 1 2 3 4 5
45

顶一下

发表我的见解...

  • 您的大名: 留空为匿名
  • 您的主页:
  • 您的邮箱:

看看大家怎么说...

  • 开心网 发表于09年11月11日 11:07

    想防止sql注入 怎么处理?

  • 创意产品 发表于09年04月26日 16:01

    不错,很有价值的东东

  • Crazy 发表于09年03月18日 15:07

    这个问题应该是可以使用USE INDEX来指定使用哪个索引的吧 你的解决办法,做后是怎么满足program_id between 1 and 4000的需求的?

  • ylcz 发表于08年09月12日 16:27

    “这是一个在千万笔记录表中由于使用了索引导致了数据查找变慢的问题” -------不是因为使用了索引吧? 我估计:id是连续的,索引快

  • Haierspi 发表于08年09月08日 23:17

    肯定了..一般WHERE 条件 都要设置索引~

  • 某游客 发表于08年08月16日 14:07

    读了两次 了解了

  • 小强 发表于08年08月11日 23:56

    印象中mysql有强行去除某一索引的,并优先某个索引的命令...这方法行吗

  • 童遥 发表于08年08月11日 23:34

    那请问这样的话对于program_id的约束是否要借助于再处理进行了?