sharding-jdbc面试题
分表的方式有哪些
垂直分表:可以将不常用的、容量大的、不同业务的字段拆出去,减少单表占用的空间
水平分表:字段数量不动,根据特定的分表算法,根据字段值路由到不同的表来进行拆分
什么场景下要进行分表
现在或可预见的单表数据量大,避免影响查询性能要进行分表
回答如:我们预估生产上每天大约有3万以上的交易数据,一年就能达到1000多万的交易数据,避免数据量太多以后再进行分表比较麻烦就提前直接先做了分表
多大量时考虑分表
mysql单表(innodb)可以存储10亿级数据,只是这时候性能很差,业界公认mysql单表在1千万以下是最佳状态,这个时候btree索引树高在3-5之间。
一般来说,当单个表的数据量达到10GB~20GB左右,或者单表中的数据量达到千万级别时,就建议进行分表操作。
阿里巴巴的《Java开发手册》提出:单表行数超过500万行或者单表容量超过2GB,才推荐进行分库分表;如果预计三年后的数据量达不到这个级别,请不要在创建表时就分库分表
为什么数据量大了就要考虑分表
innodb存储引擎的索引结构是B+树,数据量越大,树越高,访问的节点就越多,查询的效率就越低(会增加更多的磁盘访问次数(每多读一个节点就可能增加一次读磁盘的次数);树越高需要在内存中缓存更多的数据;树越高索引的维护成本也越高)。
innodb存储引擎最小的存储单位是页,一个页的大小是16K
3层的树约2千万数据,占用的内存大小大约2千万k=20G左右
假设主键ID为bigint类型,长度为8字节,而指针大小在InnoDB源码中设置为6字节,这样一共14字节,一页能存放16384/14=1170个指针
现在很多互联网业务数据一条记录大小通常就是1K左右,一个数据节点16k,存放数据和指向相邻子节点的指针,所以一个节点大约能存放16/1=16条数据
如果b+tree有两层:1170*16=18720条
如果b+tree有三层:1170*1170*16=21902400条
分表优缺点
优点:可以提高数据的查询效率,提升系统性能
缺点:
复杂性增加:表结构变动变的复杂,需要修改所有分表;需要编写路由策略保证数据正确的存储于查询
跨表:多分布在多个表的数据,需要进行跨表联合查询
分表相比分区的优缺点
分区相比分表更容易些,对程序代码来说基本透明的,分表需要专门做配置及处理代码
表结构变动时,分区相比分表容易维护,分表需要所有的表都进行维护
分区的话主键或唯一索引必须包括分区键(没有主键或索引可以用任意列),分表没有这个限制
单表最大分区数量不能超过1024个(一版建议不超过150个),分表没有这个限制
分表键怎么选择
分表键应该尽量选择那些能够将数据均匀分布到不同分表的字段。
进项选择查询频率高的字段作为分表键
常用的如用户id,时间,地区,业务类型等根据常用查询的方式避免跨表查询来选择分表的键
非分表键怎么查询
一:遍历所有表
二:常用非分表键跟分表键做关联,如关系存储到ES;或者字段中包含分表键的值,如id中可以包含时间,订单号中包括用户id
三:业务上设计功能的时候尽量把分表键设置成必填
分表策略怎么选择
水平急切分的策略一般有:
- 按数量切分,第一张存1-10000,第二张表存10001-20000
- 按时间切分,2023年一张 ,2024年一张
- 按分表键值先取哈希值再取模切分
选择的方法看热点的数据时怎么分布的:
如订单、日志,一般最近的订单查看和操作的频繁可以按时间
如果热点数据跟时间关系不大,如用户数据根据用户id进行分表,可以用哈希取模方式
分表如何不停服操作
编写一个开关控制是新老表双写,还是只写新表;上线后进行双写并使用脚本或程序进行历史数据的迁移;都迁移完成后只单写新的表即可。
sharding-jdbc简介
原来由当当网开发并维护,现在已经成为 Apache 的一个孵化项目。可以提供分库分表、读写分离、分布式事务(通过全局事务ID来管理分布式事务)等功能。
shardingJDBC目前支持MySQL、Oracle、SQL Server等主流关系型数据库
sharding-jdbc原理
SQL 解析:当你执行一个 SQL 语句时,ShardingSphere-JDBC 首先会对这个 SQL 语句进行解析,获取到 SQL 语句的类型(例如,查询、更新或删除),以及 SQL 语句涉及的表和列。SQL解析过程分为词法解析和语法解析两步,先用词法解析将SQL拆解成不可再分的原子单元。在根据不同数据库方言所提供的字典,将这些单元归类为关键字,表达式,变量或者操作符等类型。接着语法解析会将拆分后的SQL转换为抽象语法树,通过对抽象语法树遍历,提炼出分片所需的上下文,上下文包含查询字段信息(Field)、表信息(Table)、查询条件(Condition)、排序信息(Order By)、分组信息(Group By)以及分页信息(Limit)等,并标记出 SQL中有可能需要改写的位置。
执行器优化:执器优化对SQL分片条件进行优化,尽量应用到索引。
路由计算:然后,ShardingSphere-JDBC 会根据 SQL 语句中的参数和你定义的分片策略,计算出这个 SQL 语句应该在哪些分片上执行。这个过程称为路由计算。
SQL 改写:接着,ShardingSphere-JDBC 会根据路由计算的结果,将原始的 SQL 语句改写为多个针对具体分片的 SQL 语句。这个过程称为 SQL 改写。
并行执行:最后,ShardingSphere-JDBC 会并行地在各个分片上执行改写后的 SQL 语句,并收集结果。
结果合并:对于查询语句,ShardingSphere-JDBC 还会将各个分片的查询结果合并为一个统一的结果。
通过这种方式,ShardingSphere-JDBC 实现了在应用程序层面的数据库分片,使得应用程序可以在不修改代码的情况下,实现数据库的水平分片。同时,由于 ShardingSphere-JDBC 是在 JDBC 层进行操作的,因此它可以与任何支持 JDBC 的数据库一起使用。
sharding-jdbc的分片策略有那些
分片策略只是抽象出的概念,它是由分片算法和分片健组合而成,分片算法做具体的数据分片逻辑。对于分表,一个表只能选择一种分片策略。
每种策略中可以是多个分片算法的组合,每个分片算法可以对多个分片健做逻辑判断。
1. 标准分片策略:这是最常见的分片策略,只支持单分片键,它需要定义一个精确的分片算法和一个范围的分片算法。精确分片算法是必须实现的,范围分片算法是可选实现的(未实现的话如果有相关查询就会查询所有分片)
2. 复合分片策略:这种策略用于处理多分片键的情况,它需要定义一个复合分片算法。
3. 行表达式分片策略:这种策略使用 Groovy 表达式作为分片算法,适用于简单的分片需求,只能用一个分片键。只需要提供一个包含分片键的表达式,例如 "ds${user_id % 2}" 或 "order${order_id % 2}"。对于范围查询会查询所有分片。
4. Hint 分片策略:这种策略允许在代码中手动指定分片,适用于无法通过 SQL 解析确定分片的特殊情况。
分片键说明
分片键)用于分片的数据库字段,根据分表键和分片算法可以确定数据存储在哪个分片上。
分片键可以是任何字段,但通常应选择能够均匀分布数据的字段,以避免产生数据倾斜。数据倾斜是指大量的数据都集中在少数几个分片上,这会导致查询性能下降,因为大部分查询都会集中在这些分片上。
sharding-jdbc的分片算法有那些
分片算法可以理解成一种路由规则。
精确分片算法:用于处理 = 和 IN 这类精确查找的分片。例如,WHERE order_id = 1001 或 WHERE order_id IN (1001, 1002)。
范围分片算法:用于处理 BETWEEN AND、>、<、>=、<= 这类范围查找的分片。
复合分片算法:用于多个字段作为分片键的分片操作,需要在复合分片策略(ComplexShardingStrategy )下使用。
Hint 分片算法:Hint 是一种可以在代码中直接指定数据库或表的分片策略的方式。有些时候我们并没有使用任何的分片键和分片策略,可还想将 SQL 路由到目标数据库和表,就需要通过手动干预指定SQL的目标数据库和表信息,这也叫强制路由。
动态数据节点
对于按时间进行分表的情况,表的数量会随着时间增加而增加,而配置文件中需要指定所有的分表,项目启动的时候进行加载,以后执行sql的时候就以配置的为准
对于按照时间进行分表的可以编写一个定时任务用来定时的刷新数据节点,比如我定的每个月的1号和项目启动时进行更新数据节点列表
sharding-jdbc分表后怎么分页查询
不需要开发者手动处理,对于涉及到多个分表的情况,sharding-jdbc会分别按照排序查询分表的数据之后进行数据合并后返回
新表如何进行按时间创建
使用存储过程和mysql的事件,存储过程中编写建表语句,通过事件进行定时调用存储过程来完成建表。

浙公网安备 33010602011771号