在不实际执行查询的情况下确定 Oracle 查询执行时间和建议的数据大小

Posted

技术标签:

【中文标题】在不实际执行查询的情况下确定 Oracle 查询执行时间和建议的数据大小【英文标题】:Determine Oracle query execution time and proposed datasize without actually executing query 【发布时间】:2015-04-29 10:02:07 【问题描述】:

在 oracle 中是否有任何方法可以确定 sql 查询将花费多长时间来获取整个记录以及它的大小,而无需实际执行并等待整个结果。

我使用普通的 oracle SQL 选择(不是数据泵/导入等)反复下载并向用户提供数据。有时行数以百万计。

【问题讨论】:

如果您的统计数据是最新的,execution plan 将向您显示估计的行数。 但是如何获取查询将运行多长时间以及要检索的数据大小 执行计划不仅包括行数,还包括数据的大小。它还包括对运行时间的近似估计 - 但我从未见过它接近实际运行时间。 如果你有plsql然后将查询粘贴到sql窗口并按f5,它将显示你的执行计划,你可以看到查询的成本和其他有关记录的详细信息 @anudeepks "if you have plsql" 没有意义。 PL/SQL 是一种编程语言。您不能将任何内容“粘贴”到编程语言中 【参考方案1】:

除非你运行它,否则不会知道实际运行时间,但你可以尝试估计它..

    首先你可以explain plan只解释,这将运行查询——根据你当前的统计数据,它会或多或少地告诉你它将如何执行 这将没有实际的时间和精力从数据块中读取数据.. 你有大块吗 此架构是否针对查询/报告进行了规范化/反规范化? 在同一块中可以容纳多大的行,因此只需要 1 次提取?

    您期望的行数

    基于数据量 * 您的网络延迟

基于此你可以尝试估计时间

【讨论】:

【参考方案2】:

这需要很好的统计,explain plan for ...,调整sys.aux_stats,然后调整你的期望。


    良好的统计数据 解释计划估计基于优化器统计数据。确保表和索引具有最新的统计信息。在 11g 上,这通常意味着坚持使用默认设置和任务,并且仅在大量数据加载后手动收集统计信息。

    Explain plan for ... 使用这样的语句来创建和存储任何 SQL 语句的解释计划。这甚至适用于创建索引和表。

    explain plan set statement_id = 'SOME_UNIQUE_STRING' for
    select * from dba_tables cross join dba_tables;
    

    这通常是可视化解释计划的最佳方式:

    select * from table(dbms_xplan.display);
    
    
    Plan hash value: 2788227900
    
    -------------------------------------------------------------------
    | Id  | Operation              | Name  | Rows  | Bytes | Time     |
    -------------------------------------------------------------------
    |   0 | SELECT STATEMENT       |       |    12M|  5452M| 00:00:19 |
    |*  1 |  HASH JOIN RIGHT OUTER |       |    12M|  5452M| 00:00:19 |
    |   2 |   TABLE ACCESS FULL    | SEG$  |  7116 |   319K| 00:00:01 |
    ...
    

    原始数据存储在PLAN_TABLE。计划的第一行通常总结了其他步骤的估计:

    select cardinality, bytes, time
    from plan_table
    where statement_id = 'SOME_UNIQUE_STRING'
        and id = 0;
    
    CARDINALITY    BYTES         TIME
    12934699       5717136958    19
    

    调整 sys.aux_stats$ 时间估计基于存储在 sys.aux_stats 中的系统统计信息。这些是 CPU 速度、单块 I/O 读取时间等指标的数字。例如,在我的系统上:

    select * from sys.aux_stats$ order by sname
    
    SNAME            PNAME         PVAL1              PVAL2
    SYSSTATS_INFO    DSTART                           09-11-2014 11:18
    SYSSTATS_INFO    DSTOP                            09-11-2014 11:18
    SYSSTATS_INFO    FLAGS                        1    
    SYSSTATS_INFO    STATUS                           COMPLETED
    SYSSTATS_MAIN    CPUSPEED
    SYSSTATS_MAIN    CPUSPEEDNW    3201.10192837466    
    SYSSTATS_MAIN    iosEEKTIM                   10    
    SYSSTATS_MAIN    IOTFRSPEED                4096    
    SYSSTATS_MAIN    MAXTHR
    SYSSTATS_MAIN    MBRC
    SYSSTATS_MAIN    MREADTIM
    SYSSTATS_MAIN    SLAVETHR
    SYSSTATS_MAIN    SREADTIM
    

    号码可以由dbms_stats.gather_system_stats自动收集。它们也可以手动修改。这是一个 SYS 表,但修改起来相对安全。创建一些示例查询,将估计时间与实际时间进行比较,并调整数字直到它们匹配。

    发现你可能浪费了很多时间

    理论上,在所有情况下都无法正确预测运行时间,而在实践中,预测非平凡查询非常困难。乔纳森·刘易斯 (Jonathan Lewis) 写了一整篇关于这些预测的 book,而那本书只涵盖了“基础知识”。

    如果估计值相差一到两个数量级,则复杂的解释计划通常“足够好”。但这种差异通常不足以向用户展示或用于做出任何重要决定。

【讨论】:

以上是关于在不实际执行查询的情况下确定 Oracle 查询执行时间和建议的数据大小的主要内容,如果未能解决你的问题,请参考以下文章

Django ORM:在不执行 N+1 查询的情况下检索帖子和最新评论

如何在不运行实际查询的情况下检查 JDBC 语句的 SQL 语法?

如何在不影响实际文档的情况下修改 Mongoose 中的结果查询?

在不使用相关子查询的情况下重写查询

在不执行查询的情况下获取 Postgres 查询结果的类型

ElasticSearch使用 _validate API 在不执行查询的情况下验证查询