海量数据查询
主要内容
优化数据库设计
优化查询语句
使用普通索引
使用全文搜索技术
当我们对一张数据表进行查询时,数据表中的数据量如果很大,比如有几百万条记录
时,那么就要考虑如何能够使查询具有更高的效率了。
针对大数据量的数据进行查询时,如果查询的速度比较慢,那么我们就要分析问题到
底出现在什么地方,了解慢的原因,才可以针对慢的因素进行处理。
一般情况下查询速度慢的原因
硬件设备方面的原因
1. 吞吐量小,形成了瓶颈,即磁盘与内存等之间的读写效率。
2. 供 使用的内存不足或 主频低。
3. 网络速度慢等。
应用程序方面的原因
1. 查询语句中的条件语句没有设计好。
2. 一次性查询的数据量过大。
3. 查询结果中包含了很多不需要的列或行。
4. 查询算法设计不合理。
5. 没有为数据表建索引或者没有用到索引,或索引不是有用的索引,或在不该建索
引的列上创建了索引,或没有按需建索引以及查询时用到了不该用到的索引。这
是查询中导致速度慢的最常见的原因。
6. 锁机制的应用不当或发生死锁等。
对于硬件的问题的解决
1. 把数据、日志、索引分别放到不同的 设备上,增加读取速度。数据量越大,提
高 性能越重要。
2. 增加服务器内存及虚拟内存, 能支持 的内存,在数据读取的
过程中,会占用大量的内存,如果内存过小,很多执行计划及数据将无法进行很
好的缓存处理,所以执行速度也会急剧下降。
3. 采用主频高的 及多核处理器,在 中,数据提取的过程中,涉
及到很多并行度的计算,如果采用多核处理器,会在并行度计算方面有很大的提
升。
4. 提高网速等。
对于上面所说的应用程序方面的原因,下面我们从几个方面来介绍一下针对这些方面
大致来如何优化。对于数据查询优化,实在是一个很复杂的话题,很多时候还要结合具体
的业务流程来进行处理,所以仅从某几个方面向大家提出一些建议,在这些方面是我们要
注意的。
要注意,本章中所讲的情况都是针对要查询的数据量比较大的情况来说的,数据量比
较小时,如几百条以下,可以不用考虑这些问题。
1. 优化数据库设计
对于数据库的设计,要结合具体的业务逻辑以及在数据操作中可能会遇到的一些问
题综合进行考虑,这里给出几点建议。
关于数据库设计中的三大范式
在前面介绍数据库设计时,我们曾讲过数据库设计的三大范式,应用这三大范式可
以尽量减少数据库中的冗余数据,同时明确数据表和数据项的设计涵义,使其没有二义
性等,从这一点来讲,是好的,数据库中的冗余越小,占用的存储空间也会越小,检索
数据时的速度可能也会有所提高(要看减少的是何种冗余以及采用何种方式进行数据检
索)。
如前面介绍过的 表和 表,如图 及图 所示:
图 表的数据
图 表的数据
图 所示的 表,用于记录学员基本信息,图 所示的 表用于记录学员的
成绩信息。两张表具有主外键关系,主表为 ,外键表为 ,关联字段为
和 。
对于 表的设计和 表的设计并没有严格遵守三大范式,但这也可能符合实际
的需求。因为在 表中,对于地址信息的描述要结合具体的实际情况来确定是否要做进
一步的拆分处理。
如果 表中的数据在实际应用中数据量很大,并且对于地址项的搜索会频繁,这时
就要考虑将 列作适当拆分,如拆分成 !(所在省份)、!" (所在市)、
# (记录除省市之外的其它信息)三部分,拆分后比如要查找“西安”的学员,可
以按 !"$%西安’进行查询,否则,只能按 &!'%(西安()来查询了,而我们知道,采
用前者即按确定的条件进行查询要比采用后者即模糊查询效率要高得多,尤其大量的数据
查询环境下。
如果 表中的数据在实际应用中数据量不是很大,比如几千条记录,并且针对地址
的搜索也没有那么频繁,这时对于 列就可以不做拆分。
所以在数据库中设计中,适当的去遵守数据库设计的范式,既有利于程序员的编程设
计也有利于数据的操作。过度的追求数据库设计的范式,往往会加大程序员的编程工作量
同时由于操作数据时往往要跨多张表进行,要进行表的联接操作,执行效率也会很低。
在适当的时候,甚至也可以人为的为数据库设计制造一点冗余,为了查询的方便性和
查询的速度,牺牲一些存储空间来换取执行效率也是值得的。
如 表中记录了大量的信息,在实际的应用中,经常会用涉及到对 表取最后一次插
入的数据的操作,此时,如果 表中的数据量很大,可另增加一张数据表 *,专用于记录
表的最后一条记录(也有可能只是该条记录的部分数据),即在 表中插入数据后,同时
将此条数据中的部分内容同时备份于 * 表中,而 * 表中只保存一条记录,以后每次要提取
表的最后一条记录时直接从 * 表中提取即可,这样比从 表中直接查找数据通常要快得
多。
过期数据的处理
如果某数据表中的数据量增长速度很快,并且使用的频率很高,而且数据有时效性,
则可定期将该数据表中过期的数据转移到历史数据库中或清理掉,那么对于该表中的数
据进行查询时,就只针对当前库当前表中的数据进行查询就可以了,这样可以大大缩小
检索数据的范围。对于这种情况,要分析用户关心的数据,主要集中于哪一个时间段。
有的系统,某些数据的使用可能要跨越几年的时间,而有的系统则也许只有个把月,甚
至有的系统也许只关心当天的数据,这时就要视具体的情况,做具体的处理。
比如:某高速公路管理系统,用于管理某条高速公路在运营过程中的一些信息,系
统中的数据可能时效性不是很强, 年前录入的数据可能到目前每天都在用,而 个月
前录的数据也可能每天都在用,所以这种情况下就不能采用上面的办法了。再比如某
系统,有些办公数据是与时间相关的,比如当月很少会关心上上个月的月计划,那么这
时就可以定期检查,对于过期的数据,如果用户不是很关心或使用的频率较低,则可将
其定期移到历史数据库中。再如火车站售票系统,对于一些那些已经发车的售票信息,
已经不再具有有很大的意义,这时即可在发车后的某一个时间段内将这些售票信息全部
移出到历史数据库中。
将一张表中的数据分布到多张表中
某数据表中的数据量很多,那么如果可能的情况下,最好将它拆分成多张表或将数
据分布到多张表中。这样,查询可以具体定位于拆分后的某一张表,则检索数据的范围
就会大大的缩小。如某资讯类的网站,记录了与全国各个省市相关的资讯类的信息,假
设各个省与各个市记录的信息的格式是一样的,只是基于的范围不同,在数据库设计时,
如果为每个省设计一张数据表记录信息(即这个省下的所有市的信息全部都在一张表
中),那么这种情况下,单张数据表的数据量有一天也许会超过几百万条甚至上千万条
记录,用户检索某个省下的某个市的数据时,既使按照设计非常合理的条件语句在这个
数据表中查询,速度也可能会很慢,因为检索的范围太大了,这时,可以视具体情况,
为每个市甚至是每个区县设计一张数据表,这样将一个省所对应的数据分布到各个市所
对应的数据表中,则针对某个市或区县对应的数据进行检索时,检索的范围就会极大的
缩小,检索的速度也会极大的提高。而当检索整个省的数据时,再将所有市及所有的县
的数据合并即可。
降低与数据库之间往返的次数