如何查看查询转换器在 Oracle 中生成的查询

Posted

技术标签:

【中文标题】如何查看查询转换器在 Oracle 中生成的查询【英文标题】:How can I see the query that the query transformer produced in Oracle 【发布时间】:2020-04-11 11:38:13 【问题描述】:

据我所知,查询转换器会尽可能将我们的查询转换为更好的查询。所以我执行的查询和最后执行的查询数据库可以不一样。

如何查看数据库执行的最终查询?我的意思是查询转换器的结果。

【问题讨论】:

检查执行计划 【参考方案1】:

要查看优化器使用的转换后的查询,您应该使用 10053 跟踪。但是执行计划更方便,通常也足够好。

示例架构

举个简单的例子,这个模式包含两个简单的表,第二个表中的每一行都必须存在于第一个表中。

--drop table test2;
--drop table test1;

create table test1(a number primary key);
create table test2(a number primary key references test1(a));

我们想要生成一个简单的查询,其中转换后的查询将与原始查询不同。为此,以下查询具有不必要的联接。由于存在内部连接,并且 TEST2 中的每一行在 TEST1 中必须存在一次且仅存在一次,因此 Oracle 不需要进行连接。相反,Oracle 只需要从 TEST2 中读取单个表或索引。

select count(*) new_name_for_hard_parse_01
from test1
join test2 on test1.a = test2.a;

10053 跟踪

要找到优化器使用的精确查询,您需要生成 10053 跟踪。例如:

alter session set events '10053 trace name context forever, level 1';

select count(*) new_name_for_hard_parse_02
from test1
join test2 on test1.a = test2.a;

alter session set events '10053 trace name context off';

(请注意我如何为列使用了不同的名称。您需要更改查询并强制进行硬解析。否则,Oracle 可能只是重新使用现有的执行计划而不会生成跟踪。)

稍等片刻,该文件将显示在某处的跟踪目录中。根据版本和配置,该文件可能位于 USER_DUMP_DEST 或 DIAGNOSTIC_DEST 下的子目录中。例如,在我的电脑上是文件 D:\app\jon\virtual\diag\rdbms\orcl12\orcl12\trace\orcl12_ora_22576.trc

打开文件并查找如下部分:

...
Final query after transformations:******* UNPARSED QUERY IS *******
SELECT COUNT(*) "NEW_NAME_FOR_HARD_PARSE_02" FROM "JHELLER"."TEST2" "TEST2"
....

跟踪文件解释了不同的转换并显示了最终查询。

但您几乎从不想使用 Oracle 跟踪文件。跟踪文件很不方便,命令没有记录并且不能正常工作,而且您不会总是可以访问服务器文件系统。对于 99.9% 的 Oracle 性能调优,跟踪是浪费时间。

执行计划

执行计划是确定查询如何运行的更快方法,这可能是您感兴趣的。

explain plan for
select count(*) new_name_for_hard_parse_01
from test1
join test2 on test1.a = test2.a;

select * from table(dbms_xplan.display);

结果:

Plan hash value: 4187894267

------------------------------------------------------------------------
| Id  | Operation        | Name        | Rows  | Cost (%CPU)| Time     |
------------------------------------------------------------------------
|   0 | SELECT STATEMENT |             |     1 |     0   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE  |             |     1 |            |          |
|   2 |   INDEX FULL SCAN| SYS_C009744 |     1 |     0   (0)| 00:00:01 |
------------------------------------------------------------------------

执行计划显示了如何只使用一个对象。它没有说明使用了连接消除,你必须推断它。

【讨论】:

【参考方案2】:

Oracle 提供了一个工具,允许您查看查询的执行计划。这可以深入了解所执行的优化,并提供根据成本指标手动优化查询的机会。 Oracle 不会生成您可以检查的修改后的查询。

解释计划文档在这里https://docs.oracle.com/cd/B19306_01/server.102/b14211/ex_plan.htm#g42231

【讨论】:

【参考方案3】:

如果您的 Oracle 软件版本有许可,您可以尝试使用 TKPROF 实用程序。

要遵循的步骤:

alter session set tracefile_identifier= Test; 
alter session set sql_trace = true; 
select * from "Your query"; 
alter session set sql_trace = false; 
select value from v$diag_info where name = ‘Diag Trace’; 

cd  "path from the above query"

tkprof "required filename.trc" try_ex.txt

并通过 tkprof 创建的跟踪文件提供详细信息。 有关 tkprof 的更多信息,请查看 Oracle 文档。

【讨论】:

您能否通过缩进四个空格来格式化您的代码?这是edit 链接,您可以这样做。 TKPROF 不显示最终的转换查询。它确实显示了执行计划(和实际数字),但有更简单的方法来生成执行计划。 解释计划并不总是向您显示正在执行或将要执行的实际计划。 SQL Monitor 确实是最好的工具,因为它“永远在线”并且会显示实际的执行统计信息。 当第一次执行查询时,在这种情况下它会被转换,一旦执行计划存储在库缓存中,tkprof 就会显示出来。

以上是关于如何查看查询转换器在 Oracle 中生成的查询的主要内容,如果未能解决你的问题,请参考以下文章

不是从迁移中生成的查询

优化实体框架中生成的sql查询?

无法从 Kotlin 中生成的 Apollo 类构建查询(.builder() 不存在)

在 c# 中等效于在 c 编程中生成的要在 URL 查询字符串中发送的“Base64”编码的加密字节字符串

如何在 Oracle SQL Developer 中生成带有子查询的 INSERT 语句?

如何查询oracle数据库的操作记录