看到一篇文章里的案例:
说一个通过dblink查询远端数据库,原来查询很快,但是远端数据库增加了一个索引之后,查询一下子变慢了。
经过分析,发现那个通过dblink的查询语句之前是走索引的,但是远端数据库添加索引之后,如果索引的个数超过20个,就会忽略第一个建立的索引,如果查询语句恰好用到了第一个建立的索引,被忽略之后,只能走全表扫描了。
Oracle官方文档关于远端对象性能有如下介绍:
- Remote views do not have statistical data.
-
Queries on partitioned tables may not be optimized.
-
No more than 20 indexes are considered for a remote table.
-
No more than 20 columns are used for a composite index.
测试过程很长很长,这里不搬过来了,有兴趣可参考原文。
测试结论如下:
通过dblink关联本地表和远程表,如果远程表的索引少于20个,那么不受影响。如果远程表的索引增加到21个或以上,那么oracle在执行远程操作的时候,将忽略最早创建的那个索引,以20个为窗口移动,最新建立的索引会被意识到。如果查询关联条件中使用到最早创建的那个索引的字段,由于索引被忽略,会走全表扫描。
要“唤醒”原来的索引,rebuild无效,需要drop & create索引(但如果总数不变,新建之后又会有一个最旧的索引被忽略)
在本地表数据量比较少,远程表的数据量很大,索引数量超过20个,且关联条件的字段时最早索引的情况下,可以考虑使用DRIVING_SITE的hint,将本地表的数据全量到远程中,此时远程的关联查询可以意识到那个索引。是否使用hint,需要评估本地表数据全量推送到远程的成本,和远程表使用全表扫的成本。