【性能优化】6.6 [外键关联] 索引复用
6.6 索引复用
有时候维表会被先过滤再做关联。比如我们只关心某个产地的产品:
A |
|
1 |
=file("product.btx").import@b().keys@i(id) |
2 |
=file("orders.btx").cursor@b(p_id,quantity) |
3 |
=A2.switch@i(p_id,A1) |
4 |
=A3.select(p_id.state=="CA") |
5 |
=A4.groups(p_id.vendor;sum(p_id.price*quantity)) |
这样的计算量会比较大,A4 的判断要反复地取出 p_id.state 来判断,如果维表 A1 先被过滤,只剩下需要的记录,那么在 A3 的 switch@i 中就会把事实表中不合适的记录过滤掉,性能就会更好了。
A |
|
1 |
=file("product.btx").import@b().select(state=="CA") |
2 |
=file("orders.btx").cursor@b(p_id,quantity) |
3 |
=A2.switch@i(p_id,A1) |
4 |
=A3.groups(p_id.vendor;sum(p_id.price*quantity)) |
这段代码的计算量就要比前一段小很多。
但问题是,维表被过滤后成为一个排列后,它原来的索引就不能用了。switch 时会重建一个索引,而建索引也是需要时间的,需要计算主键的哈希值等等,在记录数比较多时建索引时间也不小,而且因为过滤条件不可预测,这个索引也不能事先准备。
其实,原表上的索引还是可以用的,至少哈希值不用重新计算,只要把过滤掉的记录从索引表中删除。SPL 提供了这种机制:
A |
|
1 |
=file("product.btx").import@b().keys@i(id) |
2 |
=file("orders.btx").cursor@b(p_id,quantity) |
3 |
=A1.select@i(state=="CA") |
4 |
=A2.switch@i(p_id,A3) |
5 |
=A4.groups(p_id.vendor;sum(p_id.price*quantity)) |
select@i 将在过滤后的排列上复用原表的索引。
索引复用并不会总是更快,因为要把过滤掉的记录从索引表删除,如果过滤掉的记录数很多(剩下的较少),这个动作也不会很快。而剩下记录较少时,重建索引很可能更快。具体采用哪种方式,要根据实际情况决定。