`

提升数据库性能的重要手段--冗余

阅读更多

前言

 

在程序设计中有一种常用的提升数据查询性能的手段以--空间换时间。典型的场景就是使用缓存,在查询数据库之前加一层全局共享缓存(如:redis),更有甚者在应用实例内部在加一层本地缓存。以java应用+mysql数据库为例,该架构设计方式如下:



 

 

数据查询逻辑为:

 



 

 

本地缓存的查询速度是纳秒级

Redis缓存的查询速度是毫秒级

Msyql数据的查询速度是毫秒级-秒级

 

有人会说既然本地缓存是最快的为什么不直接用本地缓存,还要使用redis缓存呢?本地缓存说白就是jvm内存,空间毕竟是有限的,再者分布式多实例部署的应用有多个jvm实例,本地缓存分散在各个实例内部不便于同步更新,使用上存在局限。具体怎么去权衡“本地缓存”和全局共享缓存不是本次讨论的重点,不再过多介绍。

 

所以为了提高性能需要把同一份数据存放三份,这就是数据冗余,典型的以空间换时间的使用场景。

 

可以发现在该场景中,最终瓶颈还是msyql数据库(在缓存失效时都会落到数据库),如果想要进一步的优化性能,一个重要的优化点还是在msyql数据库查询性能优化上(当然还有一个点就是优化程序本身)。

 

以空间换时间的方式同样适用运用到mysql数据库的性能优化中,主要体现在三个地方:表字段冗余、读写分离之镜像复制、读写分离之非对称复制。下面根据不同的场景,分别进行讲解。

 

表字段冗余

 

读书期间,在数据库表设计章节,相信大家都学习过“范式”。如果完全遵循“三范式”设计的数据库,对于数据存储来说可以极大的降低数据的存储量。但对于数据查询来说,会有很多联表查询,这会非常影响性能。对于高频查询的sql语句来说 “联表查询”绝对是个灾难。

 

这时的常用手段就是“表字段冗余”,举个真实的案例:在一个项目初期,使用一张表名为“sale_info”的表存放活动信息。随着业务的发展,该表的字段越来越多,为了防止一张表的字段太多,最简单的做法就是新增一个扩展表“sale_info_ext”,后续新增的字段都放到这张扩展表里。

 

这种简单的处理方式,解决了宽表问题。但同时又引入了新的问题,在查询活动信息时,由于业务数据分散在两张表里,经常需要做联表查询select a.xx,b.xx from sale_info a left join sale_info_ext b on a.id=b.sale_id where “省略其他条件。刚开始没有发现问题,但随着业务的增长,两张表的数据越来越多,应用程序经常出现“timeout”现象,通过分析慢查询日志有一条高频联表查询语句在中暴露出来。发现该问题后,初步做法是优化索引,也就是对省略其他条件字段加索引,但效果并不明显。

 

最后的做法是:分析者两张表的所有联表查询”sql语句,把主业务相关的字段迁移到sale_info表,把副业务相关的字段迁移到sale_info_ext表,对于主副业务都需要的常用字段 在两张表中做冗余存储。从而保证高频查询的sql语句,都是单表查询,最终解决该问题。对于一些低频查询的sql语句,仍然联表查询已经无所谓了(有时还应防止这些低频查询的sql语句转为高频)。

 

“表字段冗余”说起来原理简单,但实际操作有时会比较复杂。最重要的原则还是要根据业务划分,找准冗余点才能做到以空间换时间,否则空间消耗了时间减少--这就不是我们想要的效果了。

 

读写分离之镜像复制

 

对于“读多写少”的业务(其实大部分业务都是这种场景),最常见的以空间换时间的做法就是“读写分离”,要做读写分离 首先要做主备。对应“写”业务直接写主库,对于延迟要求不高的业务读从库。现在的问题就变为 主从同步问题,数据同步始终会有延迟(即便是采用数据库自带的,如mysqlReplication)。所以,对于不允许延迟的业务,只能读主库

 

所谓“镜像复制”就是所有备库的内容,跟主库内容完全一致。“镜像复制”,又存在两种情况一主多备多主多备。对于,延迟要求不高的业务,可以采用一主多备;对于,延迟要求高的业务,可以采用多主多备,具体做法是:写入数据时,写入多个主库(或者说写库),对于不允许延迟的业务直接从主库中读取数据,对于延迟要求不高的业务到从库读取数据。多主多备的架构设计如下:



 

 

这时会出现在同一个应用中有多个数据源的情况,一般做法是:在spring配置文件中配置多个数据源,获取数据源时通过一个工具类获取:

 

public class DataSourceUtil {
    private List<DataSource> readDatasources;//通过spring配置注入
    private List<DataSource> writeDatasources;//通过spring配置注入
    private Random random = new Random();
 
    public List<DataSource> getALLWrite(){//获取所有的写数据源
        return readDatasources;
    }
 
    public DataSource getOneWrite(){//随机获取一个写数据源 用于“非延时”读
        return readDatasources.get(random.nextInt(readDatasources.size()));
    }
 
    public DataSource getOneRead(){//随机获取一个写数据源 用于“可延时”读
        return readDatasources.get(random.nextInt(readDatasources.size()));
    }
}

 

最后这些数据源配置可以放到配置管理系统,可以实现在线切换数据库

 

读写分离之非对称复制

 

前一种镜像同步方式,是主库和备库的内容是完全相同的。在分库分表的系统中,做数据冗余还有另外一种数据冗余方式:非对称复制,主要作用就是减少查询时多张表的join操作。下面看一个真实的场景:

 

在笔者所在的一个活动页cms系统中,需要记录每个页面上的sku(商品编码),每天上线的活动页数量成千上万个,每个页面上对应的sku从几十个到几百个不等。可见数据量,是比较大,一般会进行分表存储。

 

应用中经常会 根据“活动页”id查询页面上的sku列表,为了减少表的join次数,我们用“活动页”idhash(可以直接取模,或者使用一致性hash) 进行分表,保证每个“活动页”id对应的sku都存在同一张表中。假设分8张表存储,分表方式如下:



 

 

现在要查询某个“活动页id”下的所有sku,首先通过“活动页idmod 8,计算出数据所在的表,然后通过一条简单的select语句查询该表就搞定。

 

但现在问题来了,“业务方”想要知道某个sku 今天在哪些页面上出现过,用来对比各个不同的页面推广效果。怎么办呢?如果按照上述分表,包含某个sku的的活动页id”分散在8张表里,需要进行7join操作或者查询8次进行合并 采用获取到所有的活动页id”

 

这种场景就可以使用“非对称复制”,在写入数据时,我们可以用另外的8张表存储上述相同的数据,唯一不同的地方就是分表规则改为对 sku编号进行hash(取模或者一致性hash都可以),分表方式如下:



 

 

好了,现在要查询某天某个sku出现过的活动页面有哪些,也就同样简单了,首先通过sku编号 mod 8获取到所在表,再通过一个简单的selec语句查询该表就搞定。

 

也就是说:如果查询条件是“活动页id”就使用第一种分表规则;反正就是使用第二种分表规则。都是单表唯一索引查询,查询速度也非常快。只是存储空间翻倍,这也是典型的空间换时间的场景。

 

这里讲的是单库操作,按照第二冗余方式所讲,如果需要做读写分离,这时有两种方案。方案一:两种分表方式的写入操作,都在同一个主库中进行,再通过数据库自带的同步工具同步到读库,查询时直接读读库。方案二:在写入数据时,两种分表方式分别写入不同的数据库,这时直接借助程序自己实现,也可以借助一些数据库中间件来完成。第二种方式虽然麻烦些,但如果数据量大 同时查询又很频繁,采用这种方式可以进一步实现不同的查询业务分库,单个数据库可以存储更多数据 并且降低单个数据库并发查询压力。

 

总结

 

仅对sql语句层面进行优化始终有局限,作为项目里的架构师一定要从更高层次出发,根据不同的业务场景采用不同架构设计手段,以减轻数据库的压力。这里不是说优化sql语句不重要,优化sql是需要首先做。

 

 

另外以空间换时间是架构设计中的常用手段,可以在各种不同的场景下使用,达到以多个廉价的pc机(空间),换取需要使用昂贵的大中型机采用达到的性能(时间)。

 

出处:

http://moon-walker.iteye.com/blog/2405545

 

  • 大小: 33.2 KB
  • 大小: 38 KB
  • 大小: 35.6 KB
  • 大小: 19.8 KB
  • 大小: 20.9 KB
0
0
分享到:
评论

相关推荐

    2017数据库系统概论作业-在线作业.docx

    A 数据库减少了数据冗余 B 数据库中的数据可以共享 C 数据库避免了一切数据的重复 D 数据库具有较高的数据独立性 正确答案:C 单选题 4.【第01章】数据库三级模式体系结构的划分,有利于保持数据库的( )。 A ...

    数据库的---三大范式

    数据库的设计范式是数据库设计所需要满足的规范,满足这些规范的数据库是简洁的、结构明晰的,同时,不会发生...反之则是乱七八糟,不仅给数据库的编程人员制造麻烦,而且面目可憎,可能存储了大量不需要的冗余信息。

    数据库课程设计--宾馆客房信息管理系统.pdf

    系统需求分析 需求分析是数据库系统设计的一个重要的环节。本阶段应该对整个应用情况作全面的、详细的 调查,确定特定数据库应用环境下的设计目标,收集该应用环境下针对系统设计所需要的基础数据 以及对这些数据的...

    数据库课程设计--仓库管理系统.doc

    华东交大理工学院 课 程 设 计 报 告 书 "所属课程名称 "数据库技术及应用(A)课程设计 " "题 目 "仓库管理系统 " " " " "院 (系) "电信分院 " "班 级 "10 通信 ( 1 )班 " "学 号 "。。。。。。。。。 " "学生...

    西南交通大学数据库关系数据库设计.docx-少年交作业啦

    1. 关系模式可能存在的4个问题?导致关系模式存在异常的根本原因?...最重要的有函数依赖、多值依赖、连接依赖。 3. 函数依赖的分类? 平凡函数依赖、非平凡函数依赖、完全函数依赖、部分函数依赖、传递函数依赖。

    数据库系统-招标参数---模板.doc

    " " "数据库性能 "数据库提供数据表分区能力的商务和技术许可,以" " " "便支持海量数据表的需求。 " " " "具有支持并行操作所需的技术,如并行装载,并行" " " "查询,并行创建索引等 " " " "提供分区索引视图功能 ...

    2003-S1-冗余控制系统的原理及性能优化.PDF

    2003-S1-冗余控制系统的原理及性能优化

    数据库概论第1-3章习题参考答案.doc

    第1章 绪论 习题参考答案 1、试述数据、数据库、数据库管理系统、数据库系统的概念。(参见P3、4、5页) 参考答案: 描述事物的符号记录称为数据;数据库是长期储存在计算机内的、有组织的、可共享 的数据集合;...

    数据库范式5nf-第五范式(5NF)数据库管理系统.pdf

    它旨在通过以多种格式分隔语义连接的关系来存储多值事实,以最⼤程度地减少关系 数据库中的冗余。 A relation R R is in 5NF 5NF if and only if every non-trivial join dependency in R R is implied by the ...

    数据库范式5nf-第四范式(4NF)数据库管理系统.pdf

    数据库范式5nf_第四范式(4NF)数据库管理系统 数据库范式5nf Fourth normal form (4NF) Fourth normal form (4NF) is a normal form used in , in which there are no non-trivial multivalued dependencies except...

    1991-2022年上市公司组织冗余-冗余资源-未吸收的冗余和已吸收冗余 包含构造Stata代码

    组织冗余/冗余资源未吸收的冗余和已吸收冗余 持续更新,后续关注我后免费获取更新版 本 不管什么时候毕业或者发期刊用到,都能用到最新的数据 【原创整理,严禁转载,转 载必究】 参考文献 [1]解维敏,魏化倩.市场...

    神通数据库-数据库快速入门.pdf

    效地减少数据库中的数据冗余,并为实现灵活的数据安全机制提供了基础。 • 支持存储过程 使用数据库创建应用程序时,过程语言是应用程序和数据库之间的主要编程接口。神通数据库中所提 供的过程语言是 plOSCAR。在...

    数据库简述题-数据库简答题.doc

    数据库简述题-数据库简答题 数据库简述题 1.从程序和数据之间的关系分析^p 文件系统和数据库系统之间的区别和联系。 答: (2)文件系统和数据库系统之间的联系: 均为数据组织的管理技术:均由数据管理软件管理...

    14-数据库课程设计任务书-某客运公司运输管理系统数据库设计.doc

    " "要求: " "数据库系统要根据设计内容和要求进行分析与设计,要考虑系统的完整性约 " "束,系统中的数据表设计应合理、高效,尽量减少数据冗余。(规范到3NF或" "BCNF " "3.设计工作任务及工作量的要求〔包括...

    数据库基础ACCESS2010.pptx

    数据库概述 数据库阶段 (1) 数据和程序之间彼此独立,实现共享 (2) 数据以数据库形式保存,最大限度减少冗余。 (3) 专门的数据库管理软件-------DBMS。 应用程序1 …… DBMS 应用程序2 数据库 应用程序n 数据库基础...

    论文研究-采用冗余提升不可分离小波变换的改进NSCT图像融合算法 .pdf

    采用冗余提升不可分离小波变换的改进NSCT图像融合算法,赵春晖,马丽娟,在灰度可见光与红外图像融合中,针对NSCT变换中金字塔分解(NSPFB)对细节能力捕捉不强的缺点,提出采用冗余提升变换替代NSPFB的图像融��

    [详细完整版]数据库基础.pdf

    1、 数据库基础 1、 数据库发展史 2、 每个阶段的特征(尤其是数据库管理阶段) 3、 数据库视图结构 4、 数据库应用结构 5、 简单数据库的建立 1、 三大阶段 人工管理阶段 文件管理阶段 数据库管理阶段 2、 数据库...

    S7-300软冗余调试总结--WINCC组态

    详述西门子S7-300软冗余实现过程中,WINCC的具体设置和编程方法,实现WINCC操作画面上自动和手动切换冗余控制器。有图有真相!

    高级MySQL笔记时,需要深入了解数据库的内部机制和优化技巧,以提高数据库性能和效率

    索引优化:索引是提高数据库查询速度的重要工具。可以通过分析查询语句和表结构,合理地设计和使用索引,避免全表扫描,提高查询效率。查询优化:通过合理设计查询语句、使用合适的索引、避免使用不必要的函数和操作...

    SIMATIC S7-1500 RH冗余系统使用手册_说明书.pdf

    SIMATIC S7-1500 RH冗余系统使用手册_说明书

Global site tag (gtag.js) - Google Analytics