【 使用环境 】测试环境
【问题描述】
举例A/B两表关联,语句如:
SELECT * FROM A,B WHERE A.C1=B.C1 AND A.C2=‘X’;
A表B表的主键都是C1,A表存在索引C2字段,可以用hint指定A为主表,并指定用NL关联模式,B表关联时使用主键索引吗?我原本尝试index(B primary),但是观察下来这个等价于full(B),explain提示确实变成了table full scan,不满足我想要的效果。是否无法指定主键,而需要建立一个同样列的唯一索引进行index hint指定?
你这个sql比较简单,走 NL 的时候,访问 B 表就是走索引。只不过 OB 的主键索引就是表数据自身,所以访问主键就是访问表。正常来说会看到对 B 表 的 TABLE GET(B).
不过,如果B 表数据量不大的情况下且C1就是主键,OB 可能会优化这个执行计划,对B 表的结果集直接进行 物化处理(加入 MATERIAL 算子),此时就对 B 表主键进行 FULL SCAN 了。这个优化好像没法取消。
(root@127.1:2883) [test]> explain select /*+ use_nl(c,w) */ w.w_name,c.c_last,c.c_first,c.c_credit from bmsql_warehouse w, bmsql_customer c where w.w_id=c.c_w_id and c.c_last='BARBARESE';
+--------------------------------------------------------------------------------------------------------------------------------------------+
| Query Plan |
+--------------------------------------------------------------------------------------------------------------------------------------------+
| ===================================================================== |
| |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| |
| --------------------------------------------------------------------- |
| |0 |NESTED-LOOP JOIN | |53 |146 | |
| |1 |├─TABLE RANGE SCAN |c(bmsql_customer_ind1)|53 |138 | |
| |2 |└─MATERIAL | |4 |5 | |
| |3 | └─TABLE FULL SCAN|w |4 |4 | |
| ===================================================================== |
| Outputs & filters: |
| ------------------------------------- |
| 0 - output([w.w_name], [c.c_last], [c.c_first], [c.c_credit]), filter(nil), rowset=256 |
| conds([w.w_id = c.c_w_id]), nl_params_(nil), use_batch=false |
| 1 - output([c.c_w_id], [c.c_last], [c.c_first], [c.c_credit]), filter(nil), rowset=256 |
| access([c.c_w_id], [c.c_d_id], [c.c_id], [c.c_last], [c.c_first], [c.c_credit]), partitions(p0) |
| is_index_back=true, is_global_index=false, |
| range_key([c.c_last], [c.c_first], [c.c_w_id], [c.c_d_id], [c.c_id]), range(BARBARESE,MIN,MIN,MIN,MIN ; BARBARESE,MAX,MAX,MAX,MAX), |
| range_cond([c.c_last = cast('BARBARESE', VARCHAR(1048576))]) |
| 2 - output([w.w_name], [w.w_id]), filter(nil), rowset=256 |
| 3 - output([w.w_id], [w.w_name]), filter(nil), rowset=256 |
| access([w.w_id], [w.w_name]), partitions(p0) |
| is_index_back=false, is_global_index=false, |
| range_key([w.__pk_increment]), range(MIN ; MAX)always true |
+--------------------------------------------------------------------------------------------------------------------------------------------+
22 rows in set (0.01 sec)
参考:
2 个赞
请将执行计划发一下