【问题标题】:How Oracle update statistics data?Oracle如何更新统计数据?
【发布时间】:2013-09-04 04:37:49
【问题描述】:

Oracle 实例版本:“Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production”

  • 新建一个表[ord],表中什么都没有,我们用[select * from ord]查看统计,开销是2
  • 我们在 [ord] 表中插入 1000 条记录并执行以下脚本来收集统计信息,现在成本为 9

    EXEC dbms_stats.gather_table_stats('COREBM','ORD',degree => 4,estimate_percent => null,method_opt => '对于所有列',cascade => 真的);

  • 然后我们清除 [ord] 表中的数据([delete from ord]),确保更改已提交,然后再次执行 [EXEC dbms_stats.gather_table_stats(...)] 以收集统计信息,我们看到成本仍然是 9,这与我预期的 2 不同

在[ord]表中的所有数据被删除之后,我们收集了统计信息,我不明白为什么[ord]表中的成本仍然是9,即使该表中没有任何内容。

【问题讨论】:

    标签: oracle11g statistics


    【解决方案1】:

    假设您的查询正在对表进行全面扫描,这意味着它必须读取每个块直到表的高水位线。当您对数据执行简单的DELETE 时,不会重置高水位线——Oracle 假设您将来可能会插入更多数据,因此它不会产生释放扩展区的成本,因为您删除数据只需要此后不久重新获得它们。这意味着,尽管当您拥有 1000 行数据时,全表扫描的成本与您随后拥有具有相同高水位标记的 0 行数据时一样昂贵。所以你会期望在运行DELETE 之后成本会相同。

    如果您想重置高水位线,您可以TRUNCATE 表而不是简单地删除数据。这不是你通常会做的事情,但它可以用于这种概念证明。

    【讨论】:

    • 谢谢,贾斯汀。为什么我有这个问题是因为我正在进行一个基准测试项目,该项目测试我们系统不同方面的性能。我们针对不同的数据集设计了不同的 SQL 进行性能测试,因此我们需要加载不同的数据集并运行相应的 SQL 来收集性能统计信息
    • 所以过程是这样的: - 为 TASK A 加载数据集,收集 Oracle 统计信息,然后为 TASK A 运行 SQL - 为 TASK A 清理所有数据集并加载数据为 TASK B 设置,再次收集 Oracle 统计信息,然后运行 ​​TASK B 的 SQL 由于统计信息会严重影响 CBO 生成的执行计划,因此可以收集一次统计信息以反映数据库中的真实数据统计信息我们为任务 B 加载了数据集?
    • @user1929982 - 我不确定我是否理解。如果您的实际数据库将在同一组表中同时执行任务 A 和 B,除非您要重复截断 prod 中的表,否则您需要对这两个任务的查询进行基准测试,并具有合理的高水位标记。但是,如果您真正谈论的是存储临时数据的表,那么您可能希望使用具有积极动态采样设置的全局临时表。
    • 不同任务的数据集差异很大,我们会逐个验证每个任务(不同的数据集和不同的SQL),在运行每个任务时1)加载数据集2)收集 Oracle 统计信息,我们希望当前的统计信息反映最新的统计信息 3)为此任务运行 SQL 4)清理在步骤 1 中加载的所有数据。然后重复 1~4 执行另一个任务。关键问题是我们在运行第二个任务时,如何通过 COB 获取新数据集的最新统计信息?
    • @user1929982 - 但是,就像我在回答中所说的那样,如果您只是删除数据,那么无论有 0 行数据还是 1000 行数据,表的大小都是相同的。优化器正在使用有关表状态的最新信息,先前的任务只是扩展了高水位线。您是否在问如何让优化器使用不正确的统计信息,以便它认为表扫描比实际便宜?这似乎不太可能有帮助。
    猜你喜欢
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 2014-01-27
    • 1970-01-01
    • 2021-10-20
    • 2015-04-20
    相关资源
    最近更新 更多