关系型数据库横向扩展的三种方法

本文是 Oracle Coherence 3.5一书,第一章: Achieving Performance, Scalability, and Availability Objectives,第二节:Achieving scalability中,数据库横向扩展部分的读书笔记。

传统的关系型数据库很难扩展,通常是纵向扩展,但到达一定程度时只能横向扩展。

数据库的横向扩展支持三种方法,即主从复制,集群和分片(sharding)。

主从复制

主从复制(Master-slave replication),最易配置,对应用改动最小,并可以减轻主库的负担。
主数据库可以读写,从数据库只读。最常用的场景就是实现读写分离,或业务分离,即运行报表,备份,数据仓库等应用。

这种方法的问题是主与从之间数据非完全同步,可能会读到两个不同的版本。另一个问题是,如果只有主库接受读写,那么主库迟早会过载,因此不算是真正的scale out。

不过主从库数据的延迟,有的业务是可以接受的。另外,利用一些实时复制的工具如GoldenGate,从库也是可以写的,这时可以利用从库做其它的业务,从而达到横向扩展的目的。这也算是主从复制的一个新趋势。

集群(Clustering)

集群也称为shared everything或shared disk架构。最知名的就是Oracle RAC。
1个数据库可以有多个实例,来访问共享存储上的数据库。
每一个节点都可以读写,从应用角度来看,代码无需改变。负载均衡也是自动的。

集群存在的问题包括:
* 写数据时需要内存中数据的同步,数据加速带来竞争,影响扩展性
* 难以设置和管理
* 由于存储是共享的,读操作也不能无限扩展

集群适合于读密集的应用,如数据仓库和BI。

分片(Sharding)

分区(Partition)是库内的,分片(Sharding)是库外的,也叫分表分库, 是shared nothing的架构。
Sharding即将一个大的库拆分成很多小库。如何拆和业务规则有关,可以按用户ID拆,按业务拆。如果需要Join,相关的表需要放到一个库里,避免数据库间的通讯。

Sharding也可以有两种方法,即垂直分区和水平分区。

垂直分区是按业务分,简称为分库,即不同的业务使用不同的库,互不相干。垂直分区到一定程度,也无法扩展,这时需要水平分区。

水平分区则是将一个大表拆分为小表,每个小表位于不同的库。每一个建立相同的schema。如根据主键的hash值来分区。

sharding的不足在于:
* 加大了应用代码的复杂性,需要路由到正确的shard。
* 后期增加shard需要修改应用逻辑,并需要迁移数据
* 查询和聚集(aggregation)不再简单,需要跨库联合操作
* 主数据和参照数据需要复制到所有shard,以避免跨库操作。主数据和参照数据虽然偏静态,但一旦修改,可能会有数据一致性问题。
* 跨库修改需要分布式交易处理,会限制可扩展性。因此应尽量避免。
* 单个shard的失效可能会使整个系统不可用(其实也不一定)。因此通常需要为每个shard再配置HA方案,如主从复制。

尽管有以上不足,分片对于一些大型网站还是广泛使用,如Google, eBay, Facebook, Flickr。

When the pain is great, any medicine that reduces it is good, regardless of the side effects.
这句话有点意思。

当然,还有一些其它一些新的数据库架构可以实现横向扩展,如NoSQL对于OLTP的扩展,Hadoop对于OLAP的扩展。不过已超出本文的讨论范围了。

扩展阅读

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
关系型数据库性能体系,设计和效率提升 1 1 前言 2 1.1目的 2 1.2预期的读者和阅读建议 2 2 数据库模型设计规范 2 2.1 数据库建模原则性规范 2 2.2 实体型之间关系认定规范 2 2.3 范式化1NF的规范 3 2.4 范式化2NF的规范 4 2.5 范式化3NF的规范 4 2.5 反范式化冗余字段使用规范 4 2.6 数据库对象命名基本规范 5 2.6.1遵循行业规范 5 2.6.2简单命名原则 5 2.6.3 字符范围原则 5 2.6.4字母全部大写或小写原则 6 2.6.5勿用保留词原则 6 2.6.5同义性原则 6 2.6.6富有含义原则 6 2.6.7 扩展性原则 6 3 表的设计规范 6 3.1 命名规范 6 3.1.1 表的命名规范 6 3.1.2 字段的命名规范 7 3.2 表的设计规范 7 3.2.1 指定表空间规范 7 3.2.2 表的主键规范 7 3.2.3 表的外键规范 8 3.2.4 字段类型及宽度的规范 8 3.2.5 一个表所含字段总长度的规范 8 3.2.6 一个表所含字段访问频繁度的规范 8 3.2.7 大对象字段(BLOB,CLOB)使用规范 9 3.2.8 关于字段能否为NULL值 9 3.2.9 关于冗余列的规范 9 3.2.10 使用注释的规范 9 3.2.11 一个表所含数据量的规范 10 3.2.12 增量同步表的设计规范 10 3.3 字段类型规范 10 3.3.1 不使用会发生隐式转换:INTEGER,FLOAT 10 3.3.2 不使用过时老类型:RAW,LONG,LONG RAW 10 3.3.3 国家字符集相关 10 3.3.4 不能使用大对象:BLOB,CLOB,NCLOB 11 3.3.5 不能使用高精度:TIMESTAMP 11 3.3.6 关于CHAR字段 11 4 分区表的设计规范 11 4.1 表空间及分区表的概念 11 4.1.1 表空间 11 4.1.2 分区表 11 4.2 表分区的具体作用 11 4.3 表分区的优缺点 12 4.4 分区表设计规范 12 4.2.1 不使用全局索引 12 4.2.2 RANGE分区的规范 12 4.2.3 LIST分区的规范 13 4.2.4 HASH分区的规范 13 4.2.5 RANGE-LIST分区的规范 14 4.2.6 RANGE-HASH分区的规范 14 5 索引的设计规范 15 5.1 索引分类 15 5.1.1单列索引与复合索引 15 5.1.2 唯一索引与非唯一索引 15 5.1.3 B树索引、位图索引与函数索引 15 5.2 命名规范 15 5.3 索引设计规范 15 5.3.1 指定表空间规范 16 5.3.2 主键索引的规范 16 5.3.3 唯一约束索引的规范 17 5.3.4 外键列索引的规范 17 5.3.5 复合索引的规范 17 5.3.6 函数索引的规范 17 5.3.7 位图索引的规范 18 5.3.8 反向索引的规范 18 5.3.9 分区索引的规范 18 5.3.10 索引重建的规范 18 6 其他数据库对象设计规范 18 6.1 命名规范 18 6.2 视图设计规范 19 6.2.1 尽量使用简单的视图,避免使用复杂的视图 19 6.2.2 按照必要性原则建立视图 19 6.3 存储过程、函数、触发器的设计规范 19 6.3.1 关于触发器的设计 19 7 SQL访问规范 20 7.1 尽量不要写复杂的SQL 20 7.2 避免使用SELECT * 20 7.3 INSERT时需写全列名 20 7.4 进行DML操作时使用CTAS进行数据备份 20 7.5 大数据量DML操作分多次执行 21 7.6 使用绑定变量,降低高硬解析 21 7.7 选择最有效率的表名顺序 21 7.8 关注WHERE子句中的连接顺序 21 7.9 用EXISTS替代IN 22 7.10 用表连接替换EXISTS 23 7.11用EXISTS替换DISTINCT 24 7.12 尽量用union all替换union 24 7.13 使用DECODE函数来减少处理时间 24 7.14 尽量避免用order by 25 7.15 用Where子句替换HAVING子句 25 7.16 减少多表关联 25 7.17 避免重复访问 26 7.17.1 使用group by 26 7.17.2 用表更新表 26 7.17.3竖向显示变横向显示 26 7.18 完成事务及时commit 27 7.19数据库连接及时关闭 27 7.20 索引的使用 27 7.20.1避免在索引列上使用函数或运算 27 7.20.2避免改变索引列的类型 28 7.20.3避免在索引列上使用NOT 28 7.20.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值