一:什么是分库?分表?分库分表? 典型回答?
- 分库:主要解决的是并发量大的问题。数据库连接数不足了的时候,就需要考虑分库了。
- 分表:主要解决的是数据量大的问题。假如你的单表数据量非常大,但是存储和查询的性能遇到了瓶颈,就需要考虑做分表了。
- 分库又分表:当你的数据库链接也不够了,并且单表数据量也很大导致查询比较慢。
二:分表字段如何选择?
在选择这个分表字段的时候,一定要根据实际的业务情况来做慎重的选择。
三:分表算法都有哪些?
不管什么算法,我们都需要确保一个前提,那就是同一个分表字段,经过这个算法处理后,得到的结果一定是一致的,不可变的。
- 直接取模:比如我们要分成128张表的话,就用一个整数(比如用户id,或者订单号之类的)来对128取模就行了,得到的结果如果是0002,那么就把数据放到order_0002这张表中。
- Hash取模:就是先对这个分表字段取Hash,然后在再取模。
- 按照关键字:比如按照时间,比如某个月份或者年份的数据单独放在某一个表中,或者可以按照地区分表也比较常见。
四:为啥要全局分布式ID,每张表自增不行吗?
1、id会重复,不用全局分布式id,就会导致id的重复,如果id重复了,那么全局查询就无法用id唯一定位一个数据。尤其是很多需要做数据汇总、统计的场景,会把数据同步到离线表,那么就会导致数据主键冲突,无法同步。
2、无法支持二次分表,如果后面如果要重新分表,那么就会导致表中出现重复id的情况,这是一定有问题的。
五:分表后全局ID如何生成?
对于分布式ID来说,具有以下几个特点:
● 全局唯一:必须保证全局唯一性,这个是最基本的要求。
● 高性能&高可用:需要保证ID的生成是稳定且高效的。
● 递增:根据不同的业务情况,有的会要求生成的ID呈递增趋势,也有的要求必须单调递增,也有的没有严格要求。
- UUID:不推荐使用他做唯一ID,首先UUID太长了,其次字符串的查询效率也比较慢,而且没有业务含义,根本看不懂。
- 基于某个单表做自增主键:所有的表在需要主键的时候,都到这张表中获取一个自增的ID。
问题是这个单表就变成整个系统的瓶颈,而且也存在单点问题,一旦他挂了,那整个数据库就都无法写入了。 - 雪花算法:雪花算法也是比较常用的一种分布式ID的生成方式,它具有全局唯一、递增、高可用的特点。
六:分库分表后会带来哪些问题?
- 首先,分库分表之后,所有的读和写操作,都需要带着分表字段,这样才能知道具体去哪个库、哪张表中去查询数据。如果不带的话,就得支持全表扫描。
- 还有,一旦我们从多个数据库中查询或者写入数据,就有很多事情都不能做了,比如跨库事务就是不支持的。
- 还有以前单表中很方便的分页查询、排序等等操作就都失效了。
- 还有一些其他问题,比如二次分表的问题,一致性ID的问题等
七:分库分表之后的怎么进行join操作
- 应用层 JOIN
在应用代码中单独查询各个表,然后在应用层将结果合并。
//先从数据库中查询出要查询的订单列表
List orders = getOrders();
for(OrderDO orderDO : orders){
OrderDTO orderDTO= new OrderDTO(orderDO);
//根据用户ID去users表查询用户名
String userName = getUserNameByUserId(orderDO.getuserId);
orderDTO.setUserName(userName);
} - 数据冗余
比如通过合理的数据冗余来避免跨库查询。缺点是会存在一致性问题,也会增加存储空间。 - 搜索引擎
使用Elasticsearch等搜索引擎,也是可以解决跨库JOIN的问题的,尤其是在处理大数据和复杂搜索场景时。
八:在分库分表时,如果遇到了对商品名称的模糊查询,要怎么处理?
方案就是把数据同步到 ES 中一份,然后基于 ES 针对商品名称构建倒排索引,这样在分词后就可以做全文索引提升查询效率了。
九:分库分表后,表还不够怎么办?
- 要么提前多分点
- 要么就是想办法减少数据量,如做数据归档,
- 要么就是二次分表,然后做数据迁移
十:分库分表的数量为什么一般选择2的幂?
- 可以将取模算法优化成位运算算法。
- 可以使得多张分表在多个库中均匀分配。
- 数据迁移时只需重新计算和迁移一半数据。
十一:分库分表中,如何预估需要分多少个库?多少张表?
- 分成多少,一般是一般是结合订单存量数据,以及增量数据的情况来看要分多少张表。你要知道你存量已经有多少数据量了,以及一年大概增长多少,还要知道业务上希望你的数据保留多久。
分表数量= (订单存量总数 + 预计年增长量 * 保留年限)/2000万 => 向上取最接近的2的幂 - 库的数量和表的数量之间没有必然联系,但是需要有倍数关系,如果你实在是不太好根据并发去预估库的数量,那么我给你个经验值的公式
分库数量 = 分表数量 / 8