为什么分布式系统不推荐使用(Join)多表关联查询?

简单来说

JOIN是MySQL用来进行联表操作的,用来匹配两个表的数据,筛选并合并符合我们要求的结果集,但使用了Join我们一般会对它多一点关注,在java开发手册中,禁止三个表以上关联使用Join,而对两个Join一般也要进行一个严格的评估,再它的算法中,有简单的嵌套循环连接,索引循环连接,块嵌套循环连接,但本质都是对内层表,也就是被驱动表做一个次数的优化,再普通的双层for循环到内层采用索引再到内层使用缓存,所以就得出一下几点:

  • 1.永远用小结果集驱动大结果集(其本质就是减少外层循环的数据数量)

  • 2.为匹配的条件增加索引(减少内层表的循环匹配次数)

  • 3.增大join buffer size的大小(一次缓存的数据越多,那么内层包的扫表次数就越少)

  • 4.减少不必要的字段查询(字段越少,join buffer 所缓存的数据就越多)

而使用Join本身,再后续数据量的增长,Join的效率就低了,join查询会导致大量数据进入数据库的内存,还有热数据被淘汰的可能,导致内存命中率降低,也有逻辑稍微复杂,跨领域职责的情况,导致后续系统解耦,拆表、库、服务,都是一定影响

详细来说

1、我们需要再概念上达成一致,那么在分布式的设计规划中,三个表以上的关联是禁止使用join的,其实两个表的join,我们也要对SQL进行一个严格的评估,SQL是否规范,有没有做索引,还要排除有没有其他的替代方案,之后才会使用Join。

2、即使出现两个表Join的情况,也要看是不是小表驱动大表,因为要评估未来的数据量的增长带来的影响;如果是大表驱动小表,一旦当数据量增大的时候,Join的性能就会大大降低,因为Join查询会导致大量的数据进入数据库的内存,而数据库的内存是有限的,所以当我们查询规模很大的一个Join的话,会导致之前的热数据被淘汰,这样内存的命中率也会降低,就会影响到线上的业务。

3、不能跨领域职责,就比如说你去查一个商品表的信息,需要关联用户表,但是呢这个商品和用户,它是两个不同的一个业务领域,所以说如果将商品和用户Join的话,那就相当于是已经跨了领域职责,这种情况下,后续如果要进行拆表或者拆库或者拆服务的话,就会造成非常大的影响,而且不好进行优化。那如果针对这种情况,针对单表操作,数据就会通过程序的内存进行关联,那无论是单表加缓存,还是改表单表的数据源,都是非常方便的

分库分表后怎么,怎么进行分页查询?

无论是什么分页场景,都需要有一个主表,来统一存储关键信息,那么其他的信息,都是属于主表的一个附属信息。也就是说,我们可以通过主表先分页之后,再单个占用其他表的查询方法,或者通过硬度条件来限制查询,然后在内存中进行数据拼接,最后把单页数据组装成一个比较大的Map,再进行返回,这样的话就把性能放到了业务机器上,也就是说我们如果出现性能问题的话,就可以通过增加机器来提高性能,

当主表的性能达到瓶颈的时候,是不是也要做分库分表呢?

是的,当主表的性能达到瓶颈的时候,要考虑分库分表,这时候有影响分页性能,就可以考虑使用ES,来构建一张大宽表,通过ES进行数据清洗后再进行直接查询,但是ES也有个缺点,就是比较吃内存,所以我们要放弃对数据的实施一次性,但是要保证查询性能是当前最佳方案。

Logo

更多推荐