概述
最近在看一个哥们优化sql里面,使用到了几个特殊的hint,但我总是对此不解,所以针对此问题自己做了一些测试(参考了一些资料)
1. no_unnest, unnest
unnest我们称为对子查询展开,顾名思义,就是别让子查询孤单地嵌套(nest)在里面。
所以un_unnest双重否定代表肯定,即让子查询不展开,让它嵌套(nest)在里面。
如果一个查询中的where 中出现 view 或者 子查询。那么oracle的CBO在解析着这个SQL之前要做转换,把VIEW或者子查询"打开"~ 这个操作就叫做unnest~ 然后可以把主查询和子查询中的表通过表连接的方式,生成执行计划。你可以使用NO_UNNEST这个hint来告诉CBO,不要“打开” VIEW或者子查询~ 这样VIEW或者子查询只能被当作一个独立查询,来进行解析,里面的表无法和主查询中的表进行连接
现做一个简单的实验:
SQL> select count(*) from dba_objects;
COUNT(*)
----------
60494
这里子查询自动展开(unnest),即TMP_LIUHC_1和TMP_LIUHC_2 hash join在一起。
接下来如果我们不希望TMP_LIUHC_2展开,想先让它单独的执行完,然后再来和外部查询进行一种叫做FILTER的操作。
那么我们加入hint no_unnest:
首先,子查询的返回结果集应该较小,然后外围查询的输入的distinct value也应该较小。
如果说no_unnest是为了让子查询不展开,独立的完成,那么push_subq就是为了让子查询最先进行join。
所以,这个hint其实是控制的join的顺序。
Table created
SQL> create table tmp_liuhc_4 as select * from dba_objects;
Table created
SQL> analyze table tmp_liuhc_3 compute statistics;
Table analyzed
SQL> analyze table tmp_liuhc_4 compute statistics;
Table analyzed
SQL> create index idx_tmp_liuhc_3 on tmp_liuhc_3(object_id);
Index created
这个在concept上有明确解释:
Mergeable and Unmergeable ViewsThe optimizer can merge a view into a referencing query block when the view has one or more base tables, provided the view does not contain:
-
set operators (UNION, UNION ALL, INTERSECT, MINUS)
a CONNECT BY clause
a ROWNUM pseudocolumn - aggregate functions (AVG, COUNT, MAX, MIN, SUM) in the select list
- a GROUP BY clause
- a DISTINCT operator in the select list
这里在最后,我们发现一个unmergeable view的一种情况就是view在outer join的右侧。
对于这种情况,我们熟知的merge hint也无效。
可见,对于此种身处outger join右侧的view来说,merge hint已经无能为力了。
综上,对于大家比较容易混淆的三个hint:
no_unnest/unnest是针对子查询是否展开的,push_subq是针对子查询的连接顺序的,push_pred则是针对unmergeable view使用外部查询谓词。
最后
以上就是明理台灯为你收集整理的oracle三组难缠的hint no_unnest/unnest,push_subq,push_pred的全部内容,希望文章能够帮你解决oracle三组难缠的hint no_unnest/unnest,push_subq,push_pred所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复