可阅读原文:http://c.raqsoft.com.cn/article/1545619124373?r=alice
主子表是数据库最常见的关联关系之一,最典型的包括合同和合同条款、订单和订单明细、保险保单和保单明细、银行账户和账户流水、电商用户和订单、电信账户和计费清单或流量详单。当主子表的数据量较大时,关联计算的性能将急剧降低,在增加服务器负载的同时严重影响用户体验
一、 原理解释
所谓主子表关联计算,就是针对主表的每条记录,按关联字段找到子表中对应的一批记录。以订单(主表)和订单明细(子表)为例,两者以订单ID为关联字段。下图显示了关联计算过程中对主表中一条记录的处理情况,红色箭头代表没找到对应记录(不可关联),绿色箭头代表找到了对应记录(可关联):
假设订单(主表)有m条记录,订单明细(子表)有n条记录,在不考虑优化算法时,主表中每一条记录的关联都需要遍历子表,相应的时间复杂度为O(n)。而主表一共有m条记录,所以整个计算的复杂度就是O(m*n),显然过高。虽然数据库一般会采用hash方案来优化,但在数据量较大或较多表关联时,仍然会面临时难以并行、使用外存缓存数据的问题,性能依旧会急剧下降。
而对于集算器来说,针对大主子表关联算法,可以通过两步来实现显著优化:数据有序化、归并关联。
l 数据有序化
对主表和子表,首先分别按照关联字段排序,形成有序数据。
l 归并关联
首先在主表和子表上分别用指针指向第一条记录,然后开始比对,对于主表的第一条记录,如果子表遇到匹配的记录,则表示可以关联,记录后子表指针前移;如果遇到不匹配的记录,表示主表第一条记录的关联计算完成,此时子表指针不动,主表指针下移一位,指向第二条记录。以此类推……
优化后,单条记录的关联计算可用下图示意:
可以看到,经过优化,主表中单条记录的关联只需比对部分数据,不再需要遍历子表。事实上,对主表所有记录的关联,才会遍历一次子表,也就是复杂度为O(n)。再加上主表本身会遍历一次,因此整个计算的复杂度就是O(m+n)。
这样,经过集算器优化后,算法的时间复杂度变为线性,而且不再需要生成落地的中间数据,性能自然得到大幅提升。
当然,需要注意的是,有序化本身也会耗费时间,因此这种优化方法不适合只做一次的关联算法。但在实际业务中,关联算法通常会反复执行,这时有序化的开销就是一次性的,完全可以忽略不计。