数据库优化实战

296 阅读5分钟

研究生期间做过一个项目,千万数量级数据库(单机)的优化。首先介绍一下项目背景,数据每30分钟存储一次,一次1万条数据,项目前期没有问题,经过大概两三个月左右,查询数据异常缓慢,甚至查不出来。基于这个背景,对数据库进行了故障排查和优化。

首先要做这个优化,必须连接数据库的一些原理。这里做一个简单的介绍。 未经优化的数据库性能瓶颈:1 数据量,单表达到百万级数据,则会出现查询缓慢的问题。 2 大量的复杂查询,关联多表,也无单表数据量只有十几万条,但是依旧会查询缓慢

解决方案:1 单表数据量大,采用索引,减少无用数据存储,优化数据表字段,分库分表等。 2 复杂查询:可以建立一个结果表,后台定时任务不断执行逻辑后插入到结果表,这样只需要查询简单的结果表即可(当然这个针对具体的业务场景,比如实时性不是那么高要求的查询 )

1 故障排除分析

项目在自测的时候没有出现该情况,原因是系统并未连续运行超过有10天,数据量尚未达到千万级别,由于在查询条件,时间字段建立有索引,所以当项目在前期运行时候也未出现查询特别缓慢的问题。百万级别数据,尚可以正常查询。20天后数据量接近千万级别,已经发现查询缓慢,一个月后,查询时间非常长,甚至后期查不出来。经过简单计算,一个月后数据量达千万级别以上。
'第一步' :检查数据库设置的超时时间,发现没有设置,这时会采用数据库默认的超时时间,而后台代码没有超时处理后的提示,因此一直查不出数据。设置了超时时间为0,即永远不超时,这里只想知道能否查询出。 进过半个小时终于查询出,检查出至少查询逻辑没有问题。

第二步:检查索引是否失效 1 使用语句 查看索引是否失效 select status from tale where index_name = '查询条件' 发现索引未失效

2 查看执行计划explain select data1 from table where updatetime>#'2016-10-8' 查看我的查询语句的执行计划,发现建立的索引依旧被用到了的。

3 确定索引存在,查询依旧慢,及索引不能够完全解决千万级别数据库的查询,因此需要做优化。

索引

既然前面提到了索引,我们都知道索引是解决查询缓慢的一个重要方式。索引建立一个数据和如何查询该数据的一个快速的对应方式。索引的数据结构有hash,b-tree 和b+tree等。然后针对索引分类又有聚簇索引和非聚簇索引。

hash索引:优化hash的一次定位特性,在理想情况下,速度特别快。但是他的缺点是,当重复数据较多,并且查询条件为范围查询时候,性能很低,毕竟hash是可以看做随机分布的,不具有连续性。

b_tree索引:该索引一般为数据库的默认索引。他基于b_tree,节点存储数据,只有叶子节点才存储数据。这样的好处在于避免磁盘的读取开销,可以用最小的次数定位到数据,降低了平均磁盘查找开销。

b+tree索引:节点会存储数据,磁盘开销比b_tree大。

首先结合项目,查询条件作为时间,因此设置采用聚簇索引。但是发现优化效果不大,因此考虑开勇分库分表方式。

前期优化

1 改用聚簇索引
2 减少无用字段的存储,无用数据不保持到数据库

分表

项目中数据的存储具有规律性,查询条件也具有规律性,按照时间来进行分库分表非常合适。这里只进行了分表的设计,当时由于还在学习,对分表中间件了解的不多,因此自己实现了分表的设计。

按月进行分表,该月的数据只存在对应的月表中,这样按照一年来算,数据减少到的原来数据的12分之1,单表控制在百万级别,结合索引的使用可以实现数据的快速查询

分表遇到的问题:1 如何解决新数据的写入 2 如何解决跨月份的数据查询

解决方案:1 新数据的写入,建立了写入中间件,获取当前时间,如何当前是时间对应无数据表,则进行创建月表,表名结合时间进行命名。已有表则写入到对应月表

2 跨月的查询,对查询条件进行计算,计算出横跨几个月,然后计算出对应哪几张表,开启多个线程,同时进行查询,然后对结构汇总返回。

备注:可以采用市场上的中间件实现,如mycat等

老数据的迁移

解决方案出来的,这个时候要做的是老数据表的迁移。 这个时候需要考虑如何快速的进行迁移且不影响业务的查询。 1 快速迁移,多开线程进行迁移。 2

总结

经过了业务优化,字段优化,索引优化,表优化,数据迁移等工作完成了对数据库的优化,其实数据库应该在设计初就考虑这些问题的,如何一开始就完成了该设计,可以避免很多问题。