前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【DB笔试面试612】在Oracle中,查询转换包含哪些类型?

【DB笔试面试612】在Oracle中,查询转换包含哪些类型?

作者头像
小麦苗DBA宝典
发布2019-09-29 16:07:26
1.3K0
发布2019-09-29 16:07:26
举报

题目部分

在Oracle中,查询转换包含哪些类型?

答案部分

在Oracle数据库中,用户发给Oracle让其执行的目标SQL和Oracle实际执行的SQL有可能是不同的,这是因为Oracle可能会对执行的目标SQL做等价改写,即查询转换。查询转换(Query Transformation),也叫逻辑优化(Logical Optimization),又称为查询改写(Query Rewrite)或软优化,即查询转换器在逻辑上对语句做一些语义等价转换,它是Oracle在解析目标SQL的过程中的非常重要的一步。查询转换能使优化器将目标SQL改写成语义上完全等价的SQL语句但生成的执行计划效率更高。

查询转换器依据特定的方式决定是否对查询块进行转换。按照其所依赖的方式,转换技术可以分为两类:①启发式查询转换(Heuristic Query Transformation),又称为基于规则的查询转换(Rule Based Query Transformation),启发式查询转换是基于一套规则对查询进行转换,一旦满足规则所定义的条件,则对语句进行相应的转换。启发式查询转换需要从10053事件信息中查找有关查询转换的线索,并且许多跟踪记录仅能从Oracle 11g的跟踪信息中发现。②基于代价的查询转换(Cost Based Query Transformation,CBQT)。基于代价的查询转换是否对语句进行转换则取决于语义等价语句之间的代价对比,即采用代价最小的一种。大多数基于代价的查询转换可以从执行计划的概要数据中找到线索。Oracle提供了一个隐含参数“_OPTIMIZER_COST_BASED_TRANSFORMATION”用以控制是否进行基于代价的查询转换,以及如何进行基于代价的查询转换,从而限制其对资源的消耗。

Oracle中常见的查询转换分类如下图所示:

代码语言:javascript
复制
SYS@orclasm > SET PAGESIZE 9999
SYS@orclasm > SET LINE 9999
SYS@orclasm > COL NAME FORMAT A40
SYS@orclasm > COL KSPPDESC FORMAT A50
SYS@orclasm > COL KSPPSTVL FORMAT A20
SYS@orclasm > SELECT A.INDX,
  2         A.KSPPINM NAME,
  3         A.KSPPDESC,
  4         B.KSPPSTVL 
  5  FROM   X$KSPPI  A,
  6         X$KSPPCV B
  7  WHERE  A.INDX = B.INDX
  8  AND LOWER(A.KSPPINM) LIKE  LOWER('%&PARAMETER%');
Enter value for parameter: _OPTIMIZER_COST_BASED_TRANSFORMATION
old   8: AND LOWER(A.KSPPINM) LIKE  LOWER('%&PARAMETER%')
new   8: AND LOWER(A.KSPPINM) LIKE  LOWER('%_OPTIMIZER_COST_BASED_TRANSFORMATION%')

      INDX NAME                                     KSPPDESC                                           KSPPSTVL
---------- ---------------------------------------- -------------------------------------------------- --------------------
      1935 _optimizer_cost_based_transformation     enables cost-based query transformation            LINEAR

Oracle中常见的查询转换分类如下表所示:

关于上表中的内容需要注意以下几点:

① 子查询展开通常都会提高原SQL的执行效率,因为如果原SQL不做子查询展开,那么通常情况下该子查询就会在其执行计划的最后一步才被执行,并且会走FILTER类型的执行计划,这也就意味着对于外部查询所在结果集的每一条记录,该子查询就会被执行多少次,这种执行方式的执行效率通常情况不会太高,尤其在子查询中包含两个或两个以上表连接时,此时做子查询展开后的执行效率往往会比走FILTER类型的执行计划高很多。

② 使用视图合并技术后,优化器不再单独为每个视图生成子计划,而是将视图的查询合并到整体查询中去,最终为合并和整体查询寻找到一个最优的执行计划。

③ 一般来说,如果Oracle没有做视图合并的话,那么在该SQL的执行计划中就会见到“VIEW”关键字,并且该关键字所对应的NAME列的值就是该视图的名称。

④ 由于查询转换的分类非常多,本书只对常见的重要的查询转换做介绍,其余的查询转换可以阅读其它相关的书籍。

为了方便,使用黄玮老师提供的一个存储过程sql_explain:

代码语言:javascript
复制
------------------------------------------------------------
-- 《SQL优化与调优技术详解》                             ---
-- 文件:02_01_SQL_Explain_11g.sql                       ---
-- 作者:黄玮                                            ---
-- 网站:WWW.HelloDBA.COM                                ---
-- Coyprigh (c):WWW.HelloDBA.COM 保留所有权利           ---
-- 描述:解析和显示语句执行计划                          ---
------------------------------------------------------------

/***********************************************************
** 用于11G                                                **
***********************************************************/
create or replace procedure sql_explain (stmt varchar2, 
                                         format varchar2 default 'ADVANCED', 
                                         exponly boolean default true)
------------------------------------------------------------
-- 描述:解析和显示语句执行计划                          ---
-- 来源:WWW.HelloDBA.COM                                ---
-- Coyprigh (c):WWW.HelloDBA.COM 保留所有权利           ---
--                                                       ---
-- 参数描述                                              ---
--     stmt:解析或执行的语句                            ---
--     format:执行计划输出格式,参加DBMS_XPLAN中描述    ---
--     exponly:是否仅解析                               ---
--         TRUE:仅调用EXPLAIN PLAN命令解析语句          ---
--        FALSE:执行语句后从缓存获得执行计划            ---
------------------------------------------------------------
  AUTHID CURRENT_USER 
as
  c number;
  r number;
  sqlid varchar2(100);
  childnum number;
begin
  dbms_output.enable(50000);
  if exponly then
    execute immediate 'explain plan for '||stmt;
    for xpl_rec in ( select * from table(dbms_xplan.display(null,null,format)) ) loop
        dbms_output.put_line(xpl_rec.plan_table_output);
    end loop;
  else
     c := dbms_sql.open_cursor;
     dbms_sql.parse(c,stmt,dbms_sql.native);
     r := dbms_sql.execute_and_fetch(c);
     loop
       exit when r <= 0;
       r := dbms_sql.fetch_rows(c);
     end loop;
    select distinct p.sql_id, p.child_number into sqlid, childnum 
    from v$sql_cursor sc, v$sql_plan p, v$open_cursor c, v$sqlarea q 
    where p.address=sc.PARENT_HANDLE and p.sql_id=q.sql_id and c.sql_id = q.sql_id and c.sid = SYS_CONTEXT('USERENV','SID') and q.sql_text like substr(stmt,0,30)||chr(37) and rownum<=1;
    --select distinct s.sql_id, s.child_number into sqlid, childnum from v$sql_plan s, v$sql_cursor c where s.address=c.PARENT_HANDLE and c.curno=c and rownum<=1;
    dbms_sql.close_cursor(c);
    for xpl_rec in ( select * from table(dbms_xplan.display_cursor(sqlid,childnum,format)) ) loop
        dbms_output.put_line(xpl_rec.plan_table_output);
    end loop;
  end if;
  rollback;
end;
/

grant execute on sql_explain to public;
create or replace public synonym sql_explain for sys.sql_explain;

本文选自《Oracle程序员面试笔试宝典》,作者:李华荣。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-08-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DB宝 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档