数据库查询性能优化之利器—索引(一)

标签: 数据库 性能优化 索引 | 发表时间:2012-08-25 00:58 | 作者:海 子
出处:http://www.cnblogs.com/

                   数据库查询性能优化之利器—索引(一)

  最近在做基于Android的公交查询系统的过程中,遇到一个很棘手的问题:换乘算法效率低。在直达查询和一次换乘查询的时候,问题体现的还不是很明显,能够在1s之内查询出乘车方案,而当进行二次查询的时候,基本要等一两分钟才能查询出换乘方案,这对于公交查询系统是绝对无法容忍的。于是找了大量的关于公交换乘算法方面的论文和资料进行研究,发现大多治标不治本,没有从根本上解决公交换乘算法效率低下的问题。公交换乘算法主要有以下三种思路:

  1)基于数据库的查询;

  2)采用Dijkstra或者Floyd算法或者改进的Dijkstra算法;

  3)基于矩阵的运算;

  由于在做这个系统之前就想过这个问题,是采用Dijkstra算法、矩阵运算还是基于数据库的查询。仔细分析之后还是选择了基于数据库的查询,因为对于大中型城市的公交网络,Dijkstra算法和矩阵运算根本不适用,尤其还是基于Android系统的公交查询系统(离线查询系统),举个例子,像成都市的公交网络系统有将近500条公交线路,5000个公交站点,如果采用矩阵运算或者Dijkstra算法的话,就只是直达矩阵就得有5000*5000=25000000个数据,若数据采用int类型保存,则该矩阵得占用25000000*4/(1024*1024)=95M的内存空间,这个数据对于移动设备来说想而知,是不可取的办法。因此最后采用了基于数据库查询的方案。

  在我的数据库中有两张表:cnbusw(线路表),cnbus(站点线路表)

     cnbusw的字段:

     id:线路编号,busw:线路名称,shijian:起始站和起始时间描述;

     cnbus的字段:

  zhan:站点名,xid:对应的线路编号,pm:在该线路中的位置,kind:线路类型(去程or返程or环形路线)

  后来发现在进行一次换乘查询的时候需要直达站点信息,因此添加了一个视图direct

  direct的字段:

  start:起始站,end:终点站,route:对应的线路编号,stopcount:两站之间的站点数

  在数据库中进行测试了一下:

  1)直达方案的话,直接在direct中进行查询:

   比如下面一条sql查询语句:

select * from direct where start='磨子桥' and end='春熙路南口'

     查询耗时:119.05ms

  2)一次换乘查询方案,通过direct的自连接进行查询:

     比如下面一条sql查询语句:

select s1.start as start,s1.route as route1,s1.end as zhuan,s2.route as route2,s2.end as end,s1.stopcount as count1,s2.stopcount as count2,(s1.stopcount+s2.stopcount) as stopcount from direct s1,direct s2 where s1.start='崔家店' and s2.end='磨子桥' and s1.end=s2.start and s1.route!=s2.route order by (s1.stopcount+s2.stopcount)

     查询耗时:415.32ms

  上述查询时间都在能够接受的范围之内,然后我很自然地按照上面的思路写出了三次换乘的sql查询语句,结果在查询时发现等了一分钟还没等出结果,并且sqlite可视化管理工具界面卡死了,这个很明显地告诉我二次换乘直接使用这样的sql语句是绝对不可行的,于是我想了一些办法,比如:两次换乘相当于是A->B->C->D,那么先查询经过站点D的线路中站点序号比D小的站点集合U,然后就相当于查询A到U集合中所有站点的一次换乘查询,这样就方便了,但是用sql语句查询了一下,一般U集合的大小都在400左右,然后要进行400次一次换乘查询,耗时400ms*400=160000ms=160s,怎么也得2分多钟,显然不可取。在陷入了这样的僵局之后,想了很久没想到办法,因为数据库里面的数据量很大,简单地对sql语句进行改进无法解决根本性问题。只有从数据库本身着手,于是想到了索引,以前上数据库课程的时候,老师提到过索引对于大量数据查询的时候效率提升的很明显,于是就尝试了一下,发现查询耗时一下减少了很多。在建立索引的过程中,原本想在视图上建立索引,发现似乎sqlite不支持在视图上创建索引,于是删除了direct视图,建立了direct直达表,在建立索引的时候,考虑是建立多列索引还是单列索引,分析一次换乘查询发现要将start,end,route这三列同时作为查询条件,并且要对stopcount进行排序,因此选择创建多列索引:

create index directindex on direct(start,end,route,stopcount)

  在创建索引之后,重新将上面的一次换乘查询语句执行了一次,耗时:5.59ms,查询速度提升了将近80倍,然后又将直达查询语句执行了一次,耗时0.49ms,也明显提升了不少。然后按照一次换乘的思路写出了二次换乘的sql语句进行执行,

select s1.start as start,s1.xid as route1,s1.end as zhuan1,s2.xid as route2 ,s2.end as zhuan2,s3.xid as route3,s3.end as end,s1.stopcount,s2.stopcount,s3.stopcount,(s1.stopcount+s2.stopcount+s3.stopcount) from direct s1,direct s2,direct s3 where s1.start='川大路黄河路口' and s3.end='春熙路南口' and s1.end=s2.start and s2.end=s3.start and s1.xid!=s2.xid and s2.xid!=s3.xid order by s1.stopcount+s2.stopcount+s3.stopcount

  耗时411.15ms,很好地解决查询效率低下的问题,从这里可以看出,在数据量很大的情况,建立索引和没有索引的区别简直是天壤之别,适当地建立索引能够使查询速度提升很大,关于索引的相关问题准备在后面进行进一步学习和研究。

 

本文链接

相关 [数据库 性能优化 索引] 推荐:

数据库查询性能优化之利器—索引(一)

- - 博客园_首页
                   数据库查询性能优化之利器—索引(一).   最近在做基于Android的公交查询系统的过程中,遇到一个很棘手的问题:换乘算法效率低. 在直达查询和一次换乘查询的时候,问题体现的还不是很明显,能够在1s之内查询出乘车方案,而当进行二次查询的时候,基本要等一两分钟才能查询出换乘方案,这对于公交查询系统是绝对无法容忍的.

DB2数据库性能优化介绍

- - CSDN博客数据库推荐文章
作者:chszs,转载需注明. 博客主页: http://blog.csdn.net/chszs. 前段时间,我从CSDN得到了这本书《DB2数据库性能调整和优化(第2版)》,这是一本介绍DB2数据库性能调优的书籍,此书覆盖了DB2数据库性能调优所需的全部知识和工具,而且还提供了大量的性能调优的实际案例,颇有一种“一书在手,DB2尽在掌握”的豪情.

浅谈MySQL 数据库性能优化

- - BlogJava-qileilove
数据库是 IO 密集型的程序,和其他数据库一样,主要功能就是数据的持久化以及数据的管理. 本文侧重通过优化MySQL 数据库缓存参数如查询缓存,表缓存,. 日志缓存,索引缓存,innodb缓存,插入缓存,以及连接参数等方式来对MySQL数据库进行优化.   这里先引用一句话,从内存中读取一个数据的时间消耗是微秒级别,而从普通硬盘上读取一个数据是在毫秒级别,二者相差3个数量级.

数据库索引

- - CSDN博客推荐文章
索引是由用户创建的、能够被修改和删除的、实际存储于数据库中的物理存在;创建索引的目的是使用户能够从整体内容直接查找到某个特定部分的内容. 一般来说,索引能够提高查询,但是会增加额外的空间消耗,并且降低删除、插入和修改速度. 1.聚集索引:表数据按照索引的顺序来存储的. 2.非聚集索引:表数据存储顺序与索引顺序无关.

基于SSD的数据库性能优化

- Sungelina - Hello DBA
NOR和NAND都是闪存技术的一种,NOR是Intel公司开发的,它有点类似于内存,允许通过地址直接访问任何一个内存单元,缺点是:密度低(容量小),写入和擦除的速度很慢. NAND是东芝公司开发的,它密度高(容量大),写入和擦除的速度都很快,但是必须通过特定的IO接口经过地址转换之后才可以访问,有些类似于磁盘.

MySQL 数据库性能优化之表结构

- tangfl - Sky.Jian 朝阳的天空
接着上一篇 MySQL 数据库性能优化之缓存参数优化 ,这是 MySQL数据库性能优化专题 系列的第二篇文章:MySQL 数据库性能优化之表结构. 很多人都将 数据库设计范式 作为数据库表结构设计“圣经”,认为只要按照这个范式需求设计,就能让设计出来的表结构足够优化,既能保证性能优异同时还能满足扩展性要求.

MySQL 数据库性能优化之缓存参数优化

- flychen50 - Sky.Jian 朝阳的天空
在平时被问及最多的问题就是关于 MySQL 数据库性能优化方面的问题,所以最近打算写一个MySQL数据库性能优化方面的系列文章,希望对初中级 MySQL DBA 以及其他对 MySQL 性能优化感兴趣的朋友们有所帮助. 这是 MySQL数据库性能优化专题 系列的第一篇文章:MySQL 数据库性能优化之缓存参数优化.

MySQL数据库性能优化之存储引擎选择

- - Sky.Jian 朝阳的天空
MySQL 数据库性能优化之SQL优化,这是  MySQL数据库性能优化专题 系列的第五篇文章:. MySQL数据库性能优化之存储引擎选择. 离上一篇文章已经有很长时间没有更新这个MySQL数据库性能优化专题了,时间太紧加上人之惰性,今天这里将之前就规划好的关于存储引擎选择方面的内容更新出来,希望对大家有所帮助吧.

MySQL数据库性能优化之硬件瓶颈分析

- - Sky.Jian 朝阳的天空
接着上一篇 MySQL数据库性能优化之存储引擎选择,这是 MySQL数据库性能优化专题 系列的第六篇文章: MySQL数据库性能优化之硬件优化. 在过往与很多人的交流过程中发现,在谈到基于硬件来进行数据库性能瓶颈分析的时候,常被大家误解为简单的使用更为强劲的主机或者存储来替换现有的设备. 个人觉得这其中可能存在一个非常大的误区.

MySQL 数据库性能优化之SQL优化

- - OurMySQL
注:这篇文章是以 MySQL 为背景,很多内容同时适用于其他关系型数据库,需要有一些索引知识为基础. IO永远是数据库最容易瓶颈的地方,这是由数据库的职责所决定的,大部分数据库操作中超过90%的时间都是 IO 操作所占用的,减少 IO 次数是. SQL 优化中需要第一优先考虑,当然,也是收效最明显的优化手段.