数据库优化浅谈

       数据库在大数据量情况下,我们应该如何去优化和管理,我分几方面来给大家介绍:从上到下,这里面给出的是一种优化收益的递减过程。也就是说,越向前端或者说我们在做设计的时候去做优化的话,收益越大。最开始是在设计层面做调整,然后再对应用开发层面的SQL语句的写法做优化。在真正使用大数据的时候,如果是高并发的SQL,那缩短每条SQL语句的执行时间,在海量高并发情兄下,在优化层面上其实是有很大收益的。
       其次才是在内存层面、IO层面上做调整和优化,最后才是从操作系统方面进行优化。任何数据库,它们的一些实施方法都是在操作系统之上的,所以操作系统的限制也会对数据库的运行有一定影响,但是这个层面的影响在前期已经做了设置,后续再做优化的时候收益并不大,所以最重要的还是前期的设计和架构。
       在选择架构的时候,不同的架构方式会直接导致性能的冲击,这就涉及如何有效使用多节点,通过数据分片的方式来高效利用处理能力。我们在真正做架构的时候,一个主要的策略就是扬长避短。还有就是对应用层的设计,如果不是高效设计的话,会直接导致后台数据库在真正运行的时候性能非常差,这是一般的指导规则。
       大家在做海量数据设计或者数据库调整的时候一定要分清楚数据库是属于哪种类型的。在前期设计以及编写代码的时候一定要注意这一点,这些都是直接影响后续上线效果的。这里我跟大家探讨一个优化的思路,我个人总结的是以下两点:一个是供给,一个是刺激需求方。比如说,我在需求里面提到的对数据库数据进行备份就需要有10TB的空间。对于这个需求,作为运维人员或者作为DBA,你的第一感觉是什么?第一感觉一般都是和需求提出方不发生争执,对吧?那么你需要10TB,我拿我的采购成本直接去买。无穷无尽地满足这种需求并不是一个好的思路。那么在当前这种策略下,我需要无穷无尽地给你提供空间,这种额外采购的开销。那么如果是要做更加高效的优化时,其实更重要的不是关注供给,而是关注你提出的需求到底是不是准确的或者说是不是合理的。假设他提出的是10TB的需求,那么你在技术层面有没有一些策略去减少这种需求。这是最重要的一点。
       再比如说,数据库提供一种压缩技术,在备份的时候可以启用这种技术使整个存储需求降低,那你说这时候是不是改变了原有的磁盘需求?所以我们就谈供和需两个方向。原先大家在做优化、在做备份的时候往往都是调供给,尽量给他资源。其实我们要从需求方去考虑这个需求是不是合理。与此类似的,比如说索引压缩技术,在数据库海量数据检索的时候,实际上对索引用的不多,对吧?如采用索引的话,大量的检索都是基于全表扫描的,如果再结合索引使用的话,扫索引、再扫表是不是两次开销?这两次开销对数据库的冲击是非常大的。因此在真正意义上的数据仓库中,索引用的并不是特别普遍。那么即便是你要用的话,尤其是复杂查询或者检索的时候,你的where子集的谓词当中是不是都是类似的复合查询?那种复合条件为了提升效率往往创建复合索引,那单键值索引开销就很大了。那么复合索弓开销是不是更大了?因此为了提高效率的话,我们在需求方面是可以先做调整的。比如说,定义一个规则尽量不建索引提高IO吞吐量,以便提高效率。如果无法满足的话,我们也要建立这种复合压缩索引,以便减少存储空间,使整个索引占据的空间降低。当你的索引空间降低以后,带来的收益有哪些?第一点,真正的存储空间开销降低了,第二点,内存中缓存有效数据所用空间减少了,那单位内存有效空间所对应的数据增加了,那么内存空间命中率也会提升,这会带来一系列的收益。
       还有另外一种做备份的对象,我们到底是全备还是增量备份?如果是全备的话,恢复的开销会降低,但是这时候恢复时间会很长。但是如果增量备份的话,一是可以减少存储的开销,虽然增加了一定的恢复复杂度,但是对于恢复效率是一个提升。
       这是我们的优化实质。举一个具体例子,大家在使用数据库一的时候,对于要提高这种并发量极高的SQL语句的解决效率,我们的策略是什么?缓存SQL语句的执行计划,在下次复用的时候不用再生成代码直接使用。如果你的代码中出现无穷无尽的相似的SQL语句,但是每种写法是不规范的,每个开发人员写的都不保证一致。这种现象大家都遇到过,这些代码都不一样,这就给数据库带来很大的冲击。如果作为DBA,你不了解代码,你只能希望后续不同开发人员都能用上自己写的代码,而不是相同功能别人写的代码。这种就是供给。如果我们对代码进行检查,在前期,在设计和开发的时候就发现这些问题的话,我们可以做些代码规范,使所有的开发人员为同样功能写出的代码都是相同的,这样就会大大降低数据库的开销。在数据库领域有一句话:高效不出故障的数据库,它的幸福度是相似的,如果是不幸福的数据库,却是各有各的不幸。这是我们在优化中的一个思路。
       比如你作为一个DBA,发现一个系统突然产生了大量的日志,瞬间产生了100GB。你有什么处理思路?这么大的事务开销首先要保障事物的正常运行,给它增大空间。如果你是一个优秀的DBA,你还会问为什么会产生这么大的数据量?其实你要清楚地知道日志来自哪里,不能无限增加空间来满足需求。第二点你要确保需求是不是合理的,是怎样产生的。要知道生产环境和测试环境截然不同。在开发测试环境中,日志的产生量非常少,但一旦上线后压力上来后,产生的日志量成指数增长,所以这时候DBA这一周的时间都是待命状态。针对这种问题你心里是什么感觉,肯定是马上和DBA说先给我扩空间,让我能平稳上线,然后再处理问题。他一定是调供给,不调需求。仔细思考一下发现,最开始开发和测试时用的是非归档模式,在非归档模式下数据属于直接路径加载,这样日志量是可以减少的。上线以后用的是归档模式,因为开发人员不关心数据库模式,这时我们就得思考如何在归档模式下减少日志生成,需要在表一级别减少日志产生。如果你不了解这个的话,你就只能无限增加空间。所以,尽可能在开发测试环境所有部署模式和你的上线环境保持一致。这是非常重要的原则。
       面对海量数据的时候,我们如何来应对?收益最高的肯定是前期的应用系统设计。提供一个简单的思路:通过分区减少索引开销。基于这种索引键值开销是最小的,确实能提高查询效率,但是在做架构的时候我们依然要思考它带来的晌。
       程序的一个有效设计原则是制定SQL编写规范以及限制动态SQL,都是希望在数据库需求降低的前提下做这种调整。在数据库设计层面结束以后,我们就要对SQL的执行计划有一个理解。可以适当使用一些SQL的索引技术提高数据的检索效率,大家使用最多的索引就是B树。还有另外一个规则就是保证在数据提交的时候尽量批量提交而不是逐行提交。
       在设计数据库的时候一定分清楚OLAP和OLTP这两种不同的数据处理类型,它们的优化和架构思路完全是相反的。
       比如说,在OLTP数据库中,以密集型的短小事务查询为主,大量的相似SQL执行,然后同一类型工作一般尽量缓存在内存中去完成。要使内存使用最大化,就要尽量使用B树索引技术,这样可使单列数据进行高效检索。这个时候我用的索引技术是针对海量数据短小的一个检索。再说OLAP系统中的特性就是大量的长事务、大查询。这时候选择的策略一般是分区技术、并行技术,使CPU和硬盘都跑满,尽量压到它的极致,使所有的吞吐量都能够压出来。因此基于这两种完全不同特性的数据库应该分别去设计。
       讲了这么多,我们到底应该关注哪些内容?消耗资源最多的SQL语句(比如说运行时间最长、运行频率最多),吞吐量。这是我们面对海量数据检索的时候要重点考察的方向。要尽量保证在内存中完成数据库操作,尽量用高速磁盘和缓存技术提高吞吐量,尽量分散IO,使用比较大的数据块,使用临时表技术,使用分区技术,尽量避免跨过操作,改变某个分区的查询性能,改进数据库的可用性。还有就是提高系统CPU的能力。
 

猜你喜欢

转载自my.oschina.net/zhangjie830621/blog/1796016