参考
笔记
sql语句如下:
SELECT T1.name, T2.date
FROM T1, T2
WHERE T1.id=T2.id
AND T1.color='red'
AND T2.type='CAR'
假设T1有m行,T2有n行,那么,普通情况下,应该要遍历T1的每一行的id(m),然后在遍历T2(n)中找出T2.id = T1.id的行进行join。时间复杂度应该是O(m*n)
如果没有索引的话,engine会选择hash join或者merge join进行优化。
hash join是这样的:
- 选择被哈希的表,通常是小一点的表。让我们愉快地假定是T1更小吧。
- T1所有的记录都被遍历。如果记录符合color=’red’,这条记录就会进去哈希表,以id为key,以name为value。
- T2所有的记录被遍历。如果记录符合type=’CAR’,使用这条记录的id去搜索哈希表,所有命中的记录的name的值,都被返回,还带上了当前记录的date的值,这样就可以把两者join起来了。
时间复杂度O(n+m),实现hash表是O(n),hash表查找是O(m),直接将其相加。
merge join是这样的:
1.复制T1(id, name),根据id排序。
2.复制T2(id, date),根据id排序。
3.两个指针指向两个表的最小值。
>1 2<
2 3
2 4
3 5
4.在循环中比较指针,如果match,就返回记录。如果不match,指向较小值的指针指向下一个记录。
>1 2< - 不match, 左指针小,左指针++
2 3
2 4
3 5
1 2< - match, 返回记录,两个指针都++
>2 3
2 4
3 5
1 2 - match, 返回记录,两个指针都++
2 3<
2 4
>3 5
1 2 - 左指针越界,查询结束。
2 3
2 4<
3 5
>
时间复杂度O(n*log(n)+m*log(m))。排序算法的复杂度分别是O(n*log(n))和O(m*log(m)),直接将两者相加。
在这种情况下,使查询更加复杂反而可以加快速度,因为更少的行需要经受join-level的测试?
当然了。
如果原来的query没有where语句,如
SELECT T1.name, T2.date
FROM T1, T2
是更简单的,但是会返回更多的结果并运行更长的时间。