但行好事
莫论前程❤

Oracle学习总结—- SQL语句解析过程详解

我们都知道,Oracle在执行SQL之前,需要对SQL语句进行解析。Oracle中,SQL语句可大致分为DDL和DML两类。对于DDL,因为很少被共享使用,故几乎每次执行时,都需要进行硬解析。而对于DML,会根据实际情况进行硬解析或软解析。这些过程都是如何进行的,什么是硬解析,什么又是软解析呢?我们将在下文揭晓。

SQL语句的解析过程,从总体上,可分为四个阶段:

语法检查

对SQL语句进行语法检查,检查是否有语法错误,比如from有没有写错,如果写错,则退出解析过程。

语意检查

这里主要是检查对象和权限,可分为以下三步:

  • 到数据字典里校验SQL语句中涉及的对象和列是否都存在,如果不存在,则退出解析过程。
  • 将对象进行名称转换。比如将同义词转换成实际的对象,如果转换失败,则退出解析过程。
  • 检查用户是否具有访问转换后的对象的权限。如果没有权限,则退出解析过程。

解析阶段

这一阶段主要是对SQL执行的环境进行判断,如绑定变量是否一样,语言环境是否一样等。可分为以下五步:

  • 对SQL文本进行HASH运算,并定位对象的句柄

    这里是区分大小写、空格、注释等,定位到相同的HASH桶和HASH桶内的LIBRARY CACHE 对象句柄。

  • 检查对象的相关性

    主要检查SQL对象与LIBRARY CACHE的同名对象是不是属于相同的OWNER。

  • 检查绑定变量是否一样

    主要检查以下内容:

    • 绑定名是否一样,如应用代码生成的绑定1、:SYS_B_0,与SQLPLUS生成的绑定变量:b1是不一样的。
    • 绑定数据类型和绑定变量长度是否一样,如绑定的数据类型(char、number)不一致,字符串绑定变量的长度是否一样,如绑定值1和33可能是不同的子游标。
  • 检查语言环境、排序环境是否一样

    例如,在会话级重新设置过语言环境,那么SQL是不能共享的。

  • 创建执行计划

    根据RBO或CBO,生成一个最优的执行计划,这也是最消耗CPU的一步。

执行阶段

通过前三个阶段一系列的检查通过后,SQL语句将进入执行阶段,这里可分为三步:

  • 将该游标所产生的执行计划、SQL文本等装载进library cache的若干个heap中。
  • 通过私有CURSOR来执行SQL。
  • 如果是SELECT,则需要UGA来FETCH数据。

以上就是SQL解析的全过程,当前三个阶段全部要执行的时候,就是硬解析,发生在SQL第一次执行的时候前三个阶段,省略了其中的一步,就是软解析,发生在SQL第二次执行的时候。当SQL第三次执行的时候,会把SQL的共享CURSOR复制到私有CURSOR中,由session_cached_cursors决定UGA中私有游标的数量。当SQL第四次执行的时候,会直接访问私有CURSOR,直接从第四阶段的第二步开始执行,这就是所谓的软解析。

下面再提供一个语句,以查询SQL不能被共享的原因:

select a.* , b.hash_value , b.sql_text
    from  v$sql_shared_cursor a, v$sqltext b ,x$kglcursor c
  where a.UNBOUND_CURSOR || a.SQL_TYPE_MISMATCH || a.OPTIMIZER_MISMATCH ||
        a.OUTLINE_MISMATCH || a.STSTS_ROW_MISMATCH || a.UTERAL_MISMATCH ||
        a.SEC_DEPTH_MISMATCH || a.EXPLAIN_PLAN_CURSOR ||
        a.BUFFERED_DML_MISMATCH || a.PDML_ENV_MISMATCH ||
        a.AUTH_CHECK_MISMATCH || a.BIND_MISMATCH || a.DESCRIBE_MISMATCH ||
        a.LANGUAGE_MISMATCH || a.TRANSLATION_MISMATCH ||
        a.ROW_LEVEL_SEC_MISMATCH || a.INSUFF_PRIVS || a.INSUFF_PRIVS_REM ||
        a.REMOTE_TRANS_MISMATCH || a.LOGMINER_SESSION_MISMATCH||
        a.INCOMP_LTRL_MISMATCH || a.OVERLAP_TIME_MISMATCH <>
        'nnnnnnnnnnnnnnnnnnnnnnnnn'
    and a.SQL_REDIRECT_MISMATCH || a.MV_QUERY_GEN_MISMATCH ||
        a.USER_BIND_PEEK_MISMATCH || a.TYPCHK_DEP_MISMATCH ||
        a.NO_TRIGGER_MISMATCH || a.FLASHBACK_CURSOR ||
        a.ANYDATA_TRANSFORMATION || a.INCOMPLETE_CURSOR ||
        a.TOP_LEVEL_RPI_CURSOR || a.DIFFERENT_LONG_LENGTH ||
        a.LOGICAL_STANDBY_APPLY || a.DIFF_CALL_DURN || a.BIND_UACS_DIFF ||
        a.PLSQL_CMP_SWITCHS_DIFF || a.CURSOR_PARTS_MISMATCH ||
        a.STB_OBJECT_MISMATCH || a.ROW_SHIP_MISMATCH || a.PQ_SLAVE_MISMATCH ||
        a.TOP_LEVEL_DDL_MISMATCH || a.MULTI_PX_MISMATCH ||
        a.BIND_PEEKED_PQ_MISMATCH || a.MV_REWRITE_MISMATCH ||
        a.FLASHBACK_TABLE_MISMATCH || a.LITREP_COMP_MISMATCH <>
       'nnnnnnnnnnnnnnnnnnnnnnnnnnnn'
    and a.address = c.kglhdadr
    and b.hash_value = c.kglnahsh
    and a.sql_id = b.sql_id
  order by b.hash_value, b.piece;

img

在这些原因中,简单列出常见的原因:

  • SQL_TYPE_MISMATCH:类型不匹配

AUTH_CHECK_MISMATCH:语句授权不匹配

LANGUAGE_MISMATCH:语言环境不匹配

USER_BIND_PEEK_MISMATCH:在cursor_sharing= SIMILAR模式下 where id > 1 和 where id > 2会生成2个cursor

UNBOUND_CURSOR:没有绑定

SQL的解析是比较消耗CPU的。了解它的全过程,可以让数据库管理员在分析问题的时候有比较清淅的思路,对分析SQL问题、shared_pool问题都有非常大的帮助。

赞(0) 打赏
未经允许不得转载:刘鹏博客 » Oracle学习总结—- SQL语句解析过程详解
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!

 

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏