Oracle的编译流程优化的复盘

发布时间:2023年12月19日

簡述

? ?因爲公司的數據庫是以Oracle為主的 最近在整理oracle對象以來的查詢的内容,今天做個小總結。先介紹下實驗環境是oracle11g。

Oracle的編譯的流程

? 首先復習下在 Oracle 数据库中,对象的编译过程通常遵循以下流程:

  1. 语法检查:首先,Oracle 数据库会对你提交的代码进行语法检查,确保它符合 PL/SQL 或 SQL 的语法规范。如果存在语法错误,编译过程会被中断,并返回相应的错误信息。

  2. 语义检查:在通过语法检查后,Oracle 数据库会进行更严格的语义检查。这一步骤会验证对象引用的表、列、视图等是否存在,并检查授权权限是否足够。如果存在语义错误,编译过程也会被中断,并返回相应的错误信息。

  3. 编译生成中间代码:在通过前两个步骤的检查后,Oracle 数据库会将代码编译为中间代码(Intermediate Representation),这是一种特定于数据库的内部表示形式。这个中间代码是数据库在执行时所使用的形式。

  4. 优化执行计划:在编译过程中的一个关键步骤是优化执行计划。Oracle 数据库会对查询语句进行优化,选择最有效的执行计划,以提高查询性能。这包括选择最佳的索引、连接顺序等。

  5. 生成可执行代码:在完成优化后,Oracle 数据库会根据中间代码生成最终的可执行代码。这些可执行代码可以直接在数据库中执行。

  6. 存储可执行代码:编译完成后,Oracle 数据库会将生成的可执行代码存储在数据库的数据字典中。这样,在下次执行相同的对象时,数据库可以直接使用已编译的代码,提高执行效率。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ? ? ? ? ???

? ? ?簡單來説就是oracle會 進行語法/語意檢查之後,編譯優化語法,生成可執行代碼,執行並保存在數據字典中,下次將直接從數據字典獲取可執行代碼,這樣可以減少編譯時間,提高執行效率。

Oracle的數據庫對象的重新編譯必要性

? ? ?我們都知道oracle的存儲過程/函數的創建語法,但在實際的生產中,在我們修改這些procedure和function之後,還需要進行數據庫層級對依賴這些對象的對象的進行重新編譯。

? ? ?比如說,B引用A之後,?A修改后會被數據庫自動打為invalid,引用A的B的也會被打為invalid,程序執行B的時候發現B是invalid,會重新編譯,但是因爲A是invalid,會導致B也跟著失敗,異常由此產生。

Oracle的數據庫對象的风险评估

评估object的依赖关系

查询依赖关系的树级

? 因为oracle的对象存在互相调用的情况,因此重新编译之前需要对对象的历来进行评估,这些代表了所有的对象都需要进行重新编译,在数据库繁忙的时候,有可能因为你编译object过多,导致编译时长过长,而导致设备卡死。

level代表了依赖调用的级别1级别代表直接调用,二级间接调用,由此类推。

select level,'alter '||decode(type,'PACKAGE BODY',
    'PACKAGE',type)||' '||name||' '||
     decode(type,'PACKAGE BODY','compile body','compile')||';'
from user_DEPENDENCIES
start with REFERENCED_NAME=upper('A')
connect by nocycle prior name= REFERENCED_NAME
order by level

小技巧

? 我们如果修改object的时候,想直观看到自己的修改的object是如何被其他object调用的,可以使用此语法来观察

 SELECT * FROM user_source
       WHERE TYPE = 'PROCEDURE'
             AND upper(text) LIKE upper('%A%');

?

设备调用数量的统计

? ? ?正如前面A因为被B依赖,导致A需要进行重新的compile,这由此导致了另一个问题,当会话未activate的时候,procedure会被锁住,这样将直接导致编译失败,间接导致机台停机。以下语法是判断当前的procedure被哪些设备调用,评估设备重启的影响。

select status, terminal ,username
from v$session
where sid in (
select session_id from dba_ddl_locks
where name=upper('A'))

V$SESSION 视图中的字段名及其含义如下:

  • AUDSID:会话的唯一标识符。
  • USER#:用户 ID,对应于?DBA_USERS?视图中的?USER_ID?字段。
  • USERNAME:用户名。
  • USERHOST:与会话关联的客户端计算机名称。
  • TERMINAL:与会话关联的终端设备名称。
  • PROGRAM:正在使用该会话的程序名称。
  • OSUSER:操作系统用户名称。
  • PROCESS:Oracle 进程 ID。
  • MACHINE:与该会话关联的客户端计算机名称。
  • PORT:客户端使用的端口号。
  • LOGON_TIME:会话的登录时间。
  • LAST_CALL_ET:从上次 SQL 语句调用以来经过的时间(以秒为单位)。
  • SQL_HASH_VALUE:执行的 SQL 语句的哈希值。
  • SQL_ID:执行的 SQL 语句的 SQL_ID。
  • PREV_SQL_HASH_VALUE:上一个执行的 SQL 语句的哈希值。
  • PREV_SQL_ID:上一个执行的 SQL 语句的 SQL_ID。
  • STATUS:会话状态,如 ACTIVE、INACTIVE、KILLED 等。
  • SERVER:指示会话是否使用了共享服务器(SHARED)或独立服务器(DEDICATED)的标志。
  • SCHEMA#:正在使用的模式的 ID,对应于?DBA_USERS?视图中的?DEFAULT_TABLESPACE?字段。
  • SCHEMANAME:正在使用的模式名称。
  • MODULE:应用程序模块名称。
  • MODULE_HASH:应用程序模块名称的哈希值。
  • ACTION:应用程序操作名称。
  • ACTION_HASH:应用程序操作名称的哈希值。
  • CLIENT_INFO:客户端信息字符串。

? ? ? 好,打完收工,下班

??

? ? ??

文章来源:https://blog.csdn.net/weixin_73368873/article/details/135028654
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。