本文翻译自Coding-Geek文章:《 How does a relational database work》。原文链接:http://coding-geek.com/how-databases-work/#Buffer-Replacement_strategies
本文翻译了如下章节, 介绍数据库查询优化器的归并连接的实现原理:
归并连接-Merge join
本章的内容与前面讨论过的归并排序非常类似。不同的是不用从两张关系表中拿出所有的数据,我们仅需要拿出相等的数据即可。算法基本思路是:
1. 先比较两张关系表的第一个元素。
2. 如果第一个元素相等,将这两条数据放到结果集中。然后比较下一个元素。
3. 如果不相等,取小的元素所在表的下一个元素,下一个元素可能就匹配了(译者注:在做merge join前先对两张表做由小到大的排序)。
4. 重复前面的几步操作,直到其中一张表的数据比较完了为止。
这个算法能正常运作的前提是,两张关系表的数据都已经排好序,在比价的过程中不需要回溯前面的元素。
这个是算法是一个简化版,它不需要考虑相同的数据在两组数据中出现多次的情况,即不考虑多次重复匹配。一个真实的归并连接算法仅仅因为这个问题就会复杂很多。这也是我选择一个简化版算法原因(译者注:重要的是讲清楚算法原理)。
如果两张关系表已排好序,那merge join的时间复杂度是O(N+M)。
如果两张关系表都需要排序,那么时间度是排序需要的消耗:O(N*Log(N) + M*Log(M))。
作为一个计算机专业的极客,我提供一个处理重复数据匹配的算法(我不保证它100%正确):
mergeJoin(relation a, relation b)
relation output
integer a_key:=0;
integer b_key:=0;
while (a[a_key]!=null or b[b_key]!=null)
if (a[a_key] < b[b_key])
a_key++;
else if (a[a_key] > b[b_key])
b_key++;
else //Join predicate satisfied
//i.e. a[a_key] == b[b_key]
//count the number of duplicates in relation a
integer nb_dup_in_a = 1:
while (a[a_key]==a[a_key+nb_dup_in_a])
nb_dup_in_a++;
//count the number of duplicates in relation b
integer dup_in_b = 1:
while (b[b_key]==b[b_key+nb_dup_in_b])
nb_dup_in_b++;
//write the duplicates in output
for (int i = 0 ; i< nb_dup_in_a ; i++)
for (int j = 0 ; i< nb_dup_in_b ; i++)
write_result_in_output(a[a_key+i],b[b_key+j])
a_key=a_key + nb_dup_in_a-1;
b_key=b_key + nb_dup_in_b-1;
end if
end while