如何可靠地获取查询的 SQL_ID

YoY*_*oYo 2 sql oracle sql-execution-plan

我知道这似乎是一个简单的问题 - 您可能认为存在现有的答案。然而 ...

了解我希望它具有合理的性能,因此它允许记录执行的每个查询(或者至少是大查询),而无需太多开销。

我的第一个想法是这个查询:

select sid,serial#,prev_sql_id from v$session where audsid=userenv('sessionid');
Run Code Online (Sandbox Code Playgroud)

我的想法是,如果我在目标查询之后立即运行此命令,我将sql_id通过 prev_sql_id 捕获正确的结果。

然而...我不是...我得到了不同的SQL...显然在我的目标 SELECT 语句和 的查询之间prev_sql_id,运行了其他东西。在我的例子中,审计已启用,并且我正在将插入捕获到SYS.AUD$表中。不好。

由于我这次尝试的主要目的是捕获查询的执行计划(因为它是由共享池执行和捕获的),所以我认为我可以简单地运行此查询:

SELECT *
  FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR());
Run Code Online (Sandbox Code Playgroud)

文档指出,使用NULL SQL_IDas 参数,它将在最近运行的查询上运行解释计划。我希望这能解决之前的问题。然而......我得到了将完全相同的插入到SYS.AUD$表中的计划。

您可能会说,好吧,那么只需在查询中添加注释即可轻松捕获SQL_ID,如下所示:

SELECT /* SQL: 1234-12' */ FROM DUAL;
Run Code Online (Sandbox Code Playgroud)

然后我可以尝试按如下方式查找 SQL_ID:

SELECT * FROM V$SQLAREA WHERE sql_text like '%SQL: 1234-12%';
Run Code Online (Sandbox Code Playgroud)

这将为我提供几个可能的候选者,其中V$SQLAREA也包括查询本身。这里的问题是我需要随机化运行的每个查询,这会导致我总是进行硬解析。

我尝试过其他解决方案来回顾历史,但这需要付出更大的代价。我尝试寻找其他解决方案。他们似乎都在某种程度上落后了。

相关文章:

Luk*_*zda 7

您可以使用新的SQL*Plus 选项

SET FEEDBACK ON SQL_ID;
Run Code Online (Sandbox Code Playgroud)

SQL_ID 返回所执行的 SQL 或 PL/SQL 语句的 sql_id。sql_id 将分配给预定义变量 _SQL_ID。您可以使用此预定义变量来调试已执行的 SQL 语句。该变量可以像任何其他预定义变量一样使用,例如 _USER 和 _DATE。

SQL> SET FEEDBACK ON SQL_ID
SQL> SELECT * FROM DUAL;  

D 
- 
X  

1 row selected.  
SQL_ID: a5ks9fhw2v9s1 

--
SQL> SELECT sql_text FROM v$sql WHERE sql_id = '&_sql_id';  

SQL_TEXT 
----------------------------------------------------- 
SELECT * FROM DUAL  

1 row selected. 
Run Code Online (Sandbox Code Playgroud)