目录
2、sharding-jdbc配置默认数据源、分片策略(了解)
2.4.3.1 sharding-jdbc概览
1、认识ShardingSphere
ShardingSphere是一套开源的分布式数据库中间件解决方案组成的生态圈,它由Sharding-JDBC、Sharding-Proxy、Sharding-Sidecar(计划中)这3款相互独立的产品组成。他们均提供标准化的数据分片、分布式事务和数据库治理功能,可适用于如Java同构、异构语言、容器、云原生等各种多样化的应用场景。
当前版本:3.0
官网地址:https://shardingsphere.apache.org/index_zh.html
官方文档:https://shardingsphere.apache.org/document/current/cn/overview
2、认识Sharding-JDBC
Sharding-JDBC:定位为轻量级Java框架,在java的JDBC层提供的额外服务。它使用客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架。
1、适用于任何基于java的ORM框架,eg:JPA、Hibernate、Mybatis、Spring JDBC Template或直接用JDBC。
2、基于任何第三方的数据库连接池,eg:DBCP、C3P0、BoneCP、Druid、HikariCP等。
3、支持任意实现JDBC规范的数据库。目前支持MySQL、Oracle、SQLServer、PostgreSQL。
3、认识Sharding-Proxy
Sharding-Proxy:定位为透明化的数据库代理端,提供封装了数据库二进制协议的服务端版本,用于完成对异构语言的支持。目前先提供MySQL版本,它可以使用任何兼容MySQL协议的访问客户端(eg:MySQL Command Client, MySQL Workbench)操作数据,对DBA更加友好。
1、向应用程序完全透明,可直接当做MySQL使用。
2、适用于任何兼容MySQL协议的客户端。
4、三个组件对比认识
5、混合架构
Sharding-JDBC采用无中心化架构,适用于java开发的高性能的轻量级OLTP应用;Sharding-Proxy提供静态入口,以及异构语言的支持,适用于OLAP应用以及对分片数据库进行管理和运维的场景。
ShardingSphere是多接入端共同组成的生态圈。通过混合使用Sharding-JDBC和Sharding-Proxy,并采用同一注册中心统一配置分片策略,能够灵活的搭建适用于各种场景的应用系统,架构师可以更加自由的调整适合于当前业务的最佳系统架构。
OLTP:On-Line Transaction Processing(联机事务处理过程)
OLAP:Online Analytical Processing(联机分析处理)
6、ShardingSphere功能清单
数据分片:分库 & 分表、读写分离、分布式主键
分布式事务:XA强一致事务、柔性事务(开发中)
数据库治理:配置动态化、 熔断 & 禁用、调用链路追踪、弹性伸缩(计划中)
7、ShardingSphere数据分片内核工作原理
ShardingSphere的3个产品的数据分片主要流程是完全一致的
核心由:SQL解析 => 执行器优化 => SQL路由 => SQL改写 => SQL执行 => 结果归并;的流程组成
本地参考文档:E:\meWork\study\project\subject-2\subject-2-docs\4-数据库中间件\Sharding-JDBC补充资料\01-Sharding-JDBC概览.pdf
8、规划路线图
2.4.3.2 sharding-jdbc读写分离
1、Sharding-JDBC入门使用
本地参考文档:E:\meWork\study\project\subject-2\subject-2-docs\4-数据库中间件\Sharding-JDBC补充资料\02-Sharding-JDBC入门使用.pdf
本地springboot+sharding jdbc的yml文件配置:E:\meWork\study\project\subject-2\subject-2-db-middleware\sharding-jdbc-study\src\main\resources\application.yml
sharding:
jdbc:
datasource:
names: ds0,ds1
ds0:
type: com.alibaba.druid.pool.DruidDataSource
driver-class: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.0.32:3306/db1?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
username: mike
password: mike
maxPoolSize: 50
minPoolSize: 1
ds1:
type: com.alibaba.druid.pool.DruidDataSource
driver-class: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.0.32:3306/db2?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
username: mike
password: mike
maxPoolSize: 50
minPoolSize: 1
config:
sharding:
default-data-source-name: ds0
props:
sql.show: true
mybatis:
configuration:
map-underscore-to-camel-case: true
可配置属性说明
1.1、数据源配置说明
dataSources: # 配置数据源列表,必须是有效的jdbc配置,目前仅支持MySQL与PostgreSQL,另外通过一些未公开(代码中可查,但可能会在未来有变化)的变量,可以配置来兼容其他支持JDBC的数据库,但由于没有足够的测试支持,可能会有严重的兼容性问题,配置时候要求至少有一个
master_ds_0: # 数据源名称,可以是合法的字符串,目前的校验规则中,没有强制性要求,只要是合法的yaml字符串即可,但如果要用于分库分表配置,则需要有有意义的标志(在分库分表配置中详述),以下为目前公开的合法配置项目,不包含内部配置参数
# 以下参数为必备参数
url: •jdbc:mysql://127.0.0.1:3306/demo_ds_slave_1?serverTimezone=UTC&useSSL=false # 这里的要求合法的jdbc连接串即可,目前尚未兼容MySQL 8.x,需要在maven编译时候,升级MySQL JDBC版本到5.1.46或者47版本(不建议升级到JDBC的8.x系列版本,需要修改源代码,并且无法通过很多测试case)
username: root # MySQL用户名
password: password # MySQL用户的明文密码
# 以下参数为可选参数,给出示例为默认配置,主要用于连接池控制
connectionTimeoutMilliseconds: 30000 #连接超时控制
idleTimeoutMilliseconds: 60000 # 连接空闲时间设置
maxLifetimeMilliseconds: 0 # 连接的最大持有时间,0为无限制
maxPoolSize: 50 # 连接池中最大维持的连接数量
minPoolSize: 1 # 连接池的最小连接数量
maintenanceIntervalMilliseconds: 30000 # 连接维护的时间间隔 atomikos框架需求
调用接口:E:\meWork\study\project\subject-2\subject-2-db-middleware\sharding-jdbc-study\src\main\java\com\study\mike\sharding\jdbc\controller\OrderController.java
可以看到ShardingSphere打印的日志:使用的NIO,及Logic SQL(逻辑sql)、SQL Statement、Actual SQL(实际sql)
2、sharding-jdbc读写分离
本地参考文档:E:\meWork\study\project\subject-2\subject-2-docs\4-数据库中间件\Sharding-JDBC补充资料\3 Sharding-JDBC读写分离.pdf
准备:
1、配置mysql主从复制
参考:https://blog.csdn.net/pyl574069214/article/details/105064915#4%E3%80%81mysql%E4%B8%BB%E4%BB%8E%E5%A4%8D%E5%88%B6%E7%9A%84%E9%85%8D%E7%BD%AE%E6%AD%A5%E9%AA%A4
2、应用中配置sharding-JDBC读写分离
2.1、配置项说明
本地springboot+sharding jdbc读写分离的yml文件配置:E:\meWork\study\project\subject-2\subject-2-db-middleware\sharding-jdbc-study\src\main\resources\application-rw.yml
sharding:
jdbc:
datasource:
names: ds0,ds1
ds0:
type: com.alibaba.druid.pool.DruidDataSource
driver-class: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.0.32:3306/orders?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
username: mike
password: mike
maxPoolSize: 50
minPoolSize: 1
ds1:
type: com.alibaba.druid.pool.DruidDataSource
driver-class: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.0.29:3306/orders?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
username: mike
password: mike
maxPoolSize: 50
minPoolSize: 1
config:
sharding:
default-data-source-name: ds0
masterslave:
name: ms
master-data-source-name: ds0
slave-data-source-names: ds1
props:
sql.show: true
mybatis:
configuration:
map-underscore-to-camel-case: true
2.4.3.3 sharding-jdbc分库分表
E:\meWork\study\project\subject-2\subject-2-docs\4-数据库中间件\Sharding-JDBC补充资料\4-Sharding-JDBC分库分表.pdf
1、sharding-jdbc分库分表概念
1.1、逻辑表
水平拆分的数据库(表)的相同逻辑和数据结构表的总称。eg:订单数据根据主键 % 2拆分为2张表,分别是t_order0、t_order1,他们的逻辑表名为t_order。
1.2、数据节点
数据分片的最小单元。由数据源名称和数据表组成,eg:ds0.t_order0
数据节点分布说明:
1、均匀分布:数据源能力均衡。eg:
2、自定义分布:数据源能力不均。eg:
1.3、真实表
在分片的数据库中真实存在的物理表。eg:t_order0、t_order1
1.4、分片策略
数据源分片、表分片仅是两个不同维度的分片,它们能用的分片策略规则是一样的。Sharding-jdbc中提供了常用的分片策略实现。分片策略由两部分构成:分片键、分片算法
1.5、五种分片策略
1、none 不分片策略
对应NoneShardingStrategy,不分片策略,SQL会被发给所有节点去执行,这个规则没有子项目可以配置。
2、inline 行表达式分片策略(必掌握)
对应InlineShardingStrategy。使用Groovy的表达式,提供对SQL语句中的=和IN的分片操作支持,只支持单分片键。对于简单的分片算法,可以通过简单的配置使用,从而避免繁琐的java代码开发。
eg:t_user_$->{u_id % 8}表示t_user表根据u_id模8,而分成8张表,表名称为t_user_0到t_user_7。
行表达式语法
1、${begin..end}表示范围区间
2、${[unit1,unit2,unit_x]}表示枚举值
行表达式中如果出现多个${expression}或$->{expression}表达式,整个表达式最终的结果将会根据每个子表达式的结果进行笛卡尔组合。
eg:
sharding:
jdbc:
datasource:
names: ds0,ds1
ds0:
type: com.alibaba.druid.pool.DruidDataSource
driver-class: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.0.32:3306/db1?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
username: mike
password: mike
maxPoolSize: 50
minPoolSize: 1
ds1:
type: com.alibaba.druid.pool.DruidDataSource
driver-class: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.0.32:3306/db2?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
username: mike
password: mike
maxPoolSize: 50
minPoolSize: 1
config:
sharding:
tables:
t_order:
actual-data-nodes: ds$->{0..1}.t_order$->{0..1}
database-strategy:
inline:
sharding-column: customer_id
algorithm-expression: ds$->{customer_id % 2}
table-strategy:
inline:
sharding-column: order_id
algorithm-expression: t_order$->{order_id % 2}
default-data-source-name: ds0
props:
sql.show: true
mybatis:
configuration:
map-underscore-to-camel-case: true
关键配置
config:
sharding:
tables:
t_order:
actual-data-nodes: ds$->{0..1}.t_order$->{0..1}
database-strategy:
inline:
sharding-column: customer_id
algorithm-expression: ds$->{customer_id % 2}
table-strategy:
inline:
sharding-column: order_id
algorithm-expression: t_order$->{order_id % 2}
3、standard 标准分片策略(了解)
1、对应StandardShardingStrategy。提供对SQL语句中的=、IN、between and的分片操作支持。
2、StandardShardingStrategy只支持单分片键,提供PreciseShardingAlgorithm和RangeShardingAlgorithm两个分片算法。
3、PreciseShardingAlgorithm是必选的,用于处理=和IN的分片。
4、RangeShardingAlgorithm是可选的,用于处理between and分片,如果不配置RangeShardingAlgorithm,SQL中的between and将按照全库路由处理。
eg:
sharding:
jdbc:
datasource:
names: ds0,ds1
ds0:
type: com.alibaba.druid.pool.DruidDataSource
driver-class: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.0.32:3306/db1?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
username: mike
password: mike
maxPoolSize: 50
minPoolSize: 1
ds1:
type: com.alibaba.druid.pool.DruidDataSource
driver-class: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.0.32:3306/db2?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
username: mike
password: mike
maxPoolSize: 50
minPoolSize: 1
config:
sharding:
tables:
t_order:
actual-data-nodes: ds$->{0..1}.t_order$->{0..1}
database-strategy:
standard:
sharding-column: order_time
preciseAlgorithmClassName: com.study.mike.sharding.jdbc.sharding.OrderTimePreciseShardingAlgorithm
table-strategy:
inline:
sharding-column: order_id
algorithm-expression: t_order$->{order_id % 2}
default-data-source-name: ds0
props:
sql.show: true
mybatis:
configuration:
map-underscore-to-camel-case: true
关键配置
database-strategy:
standard:
sharding-column: order_time
preciseAlgorithmClassName: com.study.mike.sharding.jdbc.sharding.OrderTimePreciseShardingAlgorithm
4、complex 复合分片策略(了解)
1、对应ComplexShardingStrategy。复合分片策略提供对SQL语句中的=、IN、between and的分片操作支持。
2、ComplexShardingStrategy支持多分片键,由于多分片键之间的关系复杂,因此并未进行过多的封装,而是直接将分片键值组合以及分片操作符透传至分片算法,完全由应用开发者实现,提供最大的灵活度。
5、hint分片策略(了解)
1、对应HintShardingStrategy。通过Hint而非SQL解析的方式分片的策略。
2、对于分片字段非SQL决定,而由其他外置条件决定的场景,可使用SQL Hint灵活的注入分片字段。SQL Hint支持通过java api和SQL注释(待实现)两种方式使用。
eg:内部系统,按照员工登录主键分库,而数据库中并无此字段。
2、sharding-jdbc配置默认数据源、分片策略(了解)
可配置默认的数据源、数据源分片策略、表分片策略
3、分布式主键
ShardingSphere提供灵活的配置分布式主键生成策略方式。在分片规则配置模块可配置每个表的主键生成策略,默认使用雪花算法(snowflake)生成64bit的长整型数据。
当前提供了SNOWFLAKE、UUID两种可用方式。
eg:
sharding:
jdbc:
datasource:
names: ds0,ds1
ds0:
type: com.alibaba.druid.pool.DruidDataSource
driver-class: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.0.32:3306/db1?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
username: mike
password: mike
maxPoolSize: 50
minPoolSize: 1
ds1:
type: com.alibaba.druid.pool.DruidDataSource
driver-class: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.0.32:3306/db2?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
username: mike
password: mike
maxPoolSize: 50
minPoolSize: 1
config:
sharding:
tables:
t_order:
actual-data-nodes: ds$->{0..1}.t_order$->{0..1}
database-strategy:
standard:
sharding-column: order_time
preciseAlgorithmClassName: com.study.mike.sharding.jdbc.sharding.OrderTimePreciseShardingAlgorithm
table-strategy:
inline:
sharding-column: order_id
algorithm-expression: t_order$->{order_id % 2}
keyGeneratorColumnName: order_id
default-data-source-name: ds0
props:
sql.show: true
mybatis:
configuration:
map-underscore-to-camel-case: true
关键配置
keyGeneratorColumnName: order_id
order_id列的类型最好为 varchar避免长度不够。
4、绑定表
指分片规则一致的主表和子表。eg:t_order表和t_order_item表,均按照order_id分片,则此两张表互为绑定表关系。绑定表之间的多表关联查询不会出现笛卡尔积关联,关联查询效率将大大提升。
其中t_order在from的最左侧,ShardingSphere将会以它作为整个绑定表的主表。所有路由计算将会只使用主表的策略,那么t_order_item表的分片计算将会使用t_order的条件。故绑定表之间的分区键要完全相同。
5、广播表(全局表)
指所有的分片数据源中都存在的表,表结构和表中的数据在每个数据库中均完全一致。适用于数据量不大且需要与海量数据的表进行关联查询的场景,eg:字典表。
6、数据分片+读写分离
2.4.3.4 sharding-jdbc事务与数据处理
1、Sharding-JDBC-分布式事务应用
官方文档:https://shardingsphere.apache.org/document/current/cn/manual/sharding-jdbc/usage/transaction/
本地参考文档地址:E:\meWork\study\project\subject-2\subject-2-docs\4-数据库中间件\Sharding-JDBC补充资料\5 Sharding-JDBC分布式事务应.pdf
1.1、SpringBootStarter使用方式
注意:@ShardingTransactionType需要同Spring的@Transactional配套使用,事务才会生效。
1.2、分布式事务应用
Atomikos参数配置
ShardingSphere默认的XA事务管理器为Atomikos。可以通过在项目的classpath中添加jta.properties来定制化Atomikos配置项。具体的配置规则请参考Atomikos的官方文档。
https://www.atomikos.com/Documentation/JtaProperties
2、Sharding-JDBC-数据治理-配置中心
实现动机
配置集中化:越来越多的运行时实例,使得散落的配置难于管理,配置不同步导致的问题十分严重。将配置集中于配置中心,可以更加有效进行管理。
配置动态化:配置修改后的分发,是配置中心可以提供的另一个重要能力。它可支持数据源、表与分片及读写分离策略的动态切换
参考地址:https://shardingsphere.apache.org/document/current/cn/manual/sharding-jdbc/usage/orchestration/
2.1、若使用zookeeper所需jar包
<!--若使用zookeeper, 请加入下面Maven坐标-->
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-orchestration-reg-zookeeper-curator</artifactId>
<version>${sharding-sphere.version}</version>
</dependency>
2.2、基于Spring boot的规则配置
#这个应用实例的名称
spring.shardingsphere.orchestration.name=orchestration-sharding-data-source
#指明是否需要用本地配置覆盖zookeeper
spring.shardingsphere.orchestration.overwrite=false
spring.shardingsphere.orchestration.registry.type=zookeeper
#zookeeper的连接地址
spring.shardingsphere.orchestration.registry.server-lists=localhost:2181
#指定名字空间
spring.shardingsphere.orchestration.registry.namespace=sharding-jdbc-orchestration
在某一个Sharding-jdbc应用上,将配置文件写好(写一份完整的配置),overwrite设置为true,启动这个应用,将本地的配置同步到配置中心,其他的应用只需配置从配置中心取配置的相关信息就可以了。
2.4.3.5 分布式数据库在网易的最佳实践(网易云课堂)
1、网易分布式数据库DDB
网易DDB是业界研发最早的分布式数据库产品之一。DDB采用服务端代理模式,提供透明分库分表服务。
分库分表的信息存储在MySQL数据库中,DBA通过master节点操作元数据信息(定义数据库、定义表.....),并且通过master节点将数据同步到QS。
QS:query server查询服务器
DDL:Data Definition Language数据库模式定义语言
DML:Data Manipulation Language数据操纵语言
![](https://i-blog.csdnimg.cn/blog_migrate/2abe65f16276af78e676de83b189b649.png)
1.1、应用场景举例
在电商场景中,使用RPC框架和微服务架构,商品、订单、库存、支付等模块使用统一的DDB存储,配合DDB的TCC柔性事务框架,解决不同模块间的分布式事务问题
1.2、实践
使用DDB在分表中,需要选择合适的字段来进行水平拆分,这个用来分表的字段叫做均衡字段,在实践中,均衡字段的选取非常重要,以下是均衡字段选择的几点建议:
1、经常作为等值条件的字段适合作为均衡字段
2、经常作为多表联合查询等值条件的字段(类似外键)适合作为均衡字段,这些表使用相同均衡策略。
3、均衡字段尽量使用数字。
4、均衡字段上根据需要建立索引。
2、数据库设计规范
2.1、基础规范
1、表必须有主键,建议使用整型作为主键
如果是字符串需要一个字符一个字符的比较,如果是数字就只需要比较一次
2、禁止使用外键,表之间的关联性和完整性通过应用层控制
3、表在设计之初,应考虑到大致的数量级,若表记录数低于1000W,尽量使用单表,不建议分表
1亿以内的数据,建议用分区表(分区表可以提高查找效率)
如果有更多的数据,就用分库分表
分库:不同的物理机器
分区:同一个机器(同一个mysql中db1库、db2库)
4、建议将大字段、访问频率低及不需要筛选的字段拆分到拓展表中(做好垂直拆分)
将经常使用到的字段放在一个表,不经常使用的字段放到另一个表
(比如:详细描述、内容很多的备注),这些字段内容多,还不经常用,会影响主表的存储量
5、控制单实例中表的总数、单个表分表个数控制在1024以内
MySQL多实例就是在一台服务器上同时开启多个不同的服务端口(eg:3306、3307)同时运行多个Mysql服务进程
2.2、列设计规范
合理使用字段类型
1、正确区分tinyint、int、bigint的范围
与java的4个整数类型对应
2、使用varchar(20)存储手机号,不要使用整数
1、有时候需要区分国别,会有+、-这种符号
2、手机号就是一个号码,不会做数学运算的
3、有时候需要做模糊查询
3、使用int存储IPV4,不要用char(15)
有时需要对网址做区间段的查询
4、涉及金额使用decimal,并指定精度
所有字段应定义为NOT NULL并设置默认值
1、存储NULL需要更多的空间,并且使得索引和统计变得更复杂
2.3、索引规范
1、唯一索引使用 uniq_[字段名] 来命名
2、非唯一索引使用 idx_[字段名] 来命名
3、不建议在频繁更新的字段上建立索引
4、非必要,不要进行join查询,如果要进行join查询,被join的字段必须类型相同,并建立索引
如果数据类型不同,索引就会失效
5、单张表索引数量建议控制在5个以内,索引过多,不仅会导致插入更新性能下降,还可能导致MySQL使用错误的索引,可在语句中加上force index来强制使用某个索引
6、组合索引字段数不建议超过5个,理解组合索引最左前缀原则,避免重复建设索引
eg:如果建立了索引(a,b,c),相当于建立了(a)、(a,b)、(a,b,c),这3个索引
查询条件最好根据索引来
查询条件也要出现a、b、c,这样才能最好利用索引,如果没有a,只有b、c,查询时就需要遍历所有的a
2.4、SQL规范
1、禁止使用select *,select *会增加CPU、IO、内存、带宽的消耗,指定字段能有效利用索引覆盖指定字段查询
2、insert必须指定字段,禁止使用insert into T values(),指定字段插入,在表结构变更时,能保证对应用程序无影响
3、隐式类型转换会使索引失效,导致全表扫描
eg:通过手机号搜索时,未转成字符串
4、禁止在where条件列使用函数或者表达式,导致不能命中索引,全表扫描
如果经常需要用到函数查询,可以建一个函数索引
函数索引:MySQL 8.0.13 以及更高版本支持函数索引,https://blog.csdn.net/horses/article/details/85059678
5、禁止负向查询以及%开头的模糊查询,导致不能命中索引,全表扫描
负向查询:not、非,这些不会走索引,会全表扫描,https://www.jianshu.com/p/20361fe96f0a
如果数据量很大(几千万数据)、经常需要用%开头的模糊查询,可以用全文索引
全文索引:https://blog.csdn.net/mrzhouxiaofei/article/details/79940958
文本排序(字符索引排序):将每一个字符根据编码集(UTF-8)转成编码值,根据每个字符的编码值进行排序
按照文本内容第一个字符、第二字符进行排序
也就是说内容的第一个字符相同的,会挨着排,根据第二个字符判断谁排前面,以此类推
6、避免直接返回大结果集造成内存溢出,可采用分段和游标方式
游标:Mysql中游标只适用于存储过程以及函数。https://www.cnblogs.com/progor/p/8875100.html
什么是索引:https://www.cnblogs.com/wwxzdl/p/11116446.html
7、返回结果集时尽量使用limit分页显示
8、避免出现较大的limit和offset值
9、使用group by或order by的语句,即使 用了limit offset,如果没有合适的索引做排序操作,也会遍历所有满足where条件的结果
代码示例:
语句1:select * from student limit 9,4
语句2:slect * from student limit 4 offset 9
// 语句1和2均返回表student的第10、11、12、13行
//语句2中的4表示返回4行,9表示从表的第十行开始
10、大表扫描操作尽量放到镜像库上做
镜像库、主从热备
11、禁止大表join和子查询
12、同一个字段上的OR必须改写为IN,IN的值必须少于1024个
13、应用程序必须捕获SQL异常,方便定位线上问题
3、对表进行垂直拆分
将一个属性较多的表、一行数据较大的表,将不同的属性拆分到不同的表中,以降低单库中的表的大小
3.1、特点
1、每个表的结构不一致
2、每个表的数据都是全量
3、表之间至少有一列的关联数据,一般是主键
4、所有表的并集是全量数据
3.2、原则
1、将长度较短,访问频率较高的放入一张表,如主表
2、将长度较长、访问频率较低的字段放入拓展表
3、将经常一起访问的字段放入一张表
4、水平拆分
1、场景:云课堂消息系统,主要涉及3张表:用户表、消息模板表、消息表
2、业务需求
1、用户查看最近收到的消息(99%的场景会用)
2、用户回查历史消息(使用概率:0.5%)
3、后台查询单个消息模板发给哪些用户(使用概率:0.5%)
3、表设计
1、结合业务需求,大部分场景都是通过用户id查看消息,因此用户表、消息表均以user_id作为均衡字段(分表的字段),消息模板表则以id作为均衡字段,便于组装消息。
2、消息表会随着时间逐渐增大,继而难以维护并降低数据库性能,因此根据创建时间进行分区,分隔最近消息和历史消息,便于热冷分离。
5、如何平滑添加字段
1、场景:在开发时,有时需要给表加个字段,在大数据量且分表的情况下,怎样平滑添加
2、常用方案
1、直接alter table add column,数据量大时不建议
(写锁、耗时间)
2、提前预留字段
(不优雅、造成空间浪费、预留多少很难控制,拓展性差)
3、新增一张表,在新表增加字段,迁移原表数据(pt-online-schema-change),再重命名新表为原表
(数据量很大时,迁移数据很麻烦)
4、放入extInfo,也就是加扩展表
(无法使用索引)
5、提前设计,使用key-value方式存储,新增字段时,直接加一个key就好了(优雅)
3、案例
在设计优惠系统时,优惠劵存在适用范围,eg:拼团、秒杀活动的互斥、使用端的限制......这些信息如何设计?
4、设计
这种场景适合采用方案5进行拓展,将拼团是否可用、秒杀是否可用、ios是否可用......作为一个key,而不是一个属性挂在优惠表上,以后再添加andriod是否可用,会员是否可用时,直接增加key即可完成扩展。
(优惠设置表以优惠劵模板id进行水平分表)