【问题标题】:Should creating an index instantly update Oracle's query plan?创建索引是否应该立即更新 Oracle 的查询计划?
【发布时间】:2011-03-19 15:59:30
【问题描述】:

如果您的查询效率低下,并且您添加了索引来提高性能,那么查询是否应该“立即”开始使用索引?

或者你需要清除runningalter system flush shared_pool;的Oracle“缓存”(我相信是v$sql)?

【问题讨论】:

    标签: oracle indexing oracle10g sql-execution-plan


    【解决方案1】:

    正如 DBA 喜欢回答的那样,“这取决于。”

    这取决于 Oracle 是否认为索引有助于提高性能。如果 Oracle 认为索引不是查询的最佳选择,那么 Oracle 无论如何都不会使用它。

    这取决于您是否使用准备好的语句。准备好的语句在其生命周期内不会重新解析,因此如果正在运行的应用程序使用您尝试修复的准备好的语句,您将需要重新启动应用程序。

    刷新共享池将迫使 Oracle 重新解析和重新优化所有语句(硬解析),因此如果 Oracle 认为索引有助于提高性能,那么刷新共享池就可以解决问题。但是,它也可能在实时生产系统中产生深远的影响——导致“解析风暴”,因为使用中的每个语句都必须重新解析和重新优化——并且只能作为最后的手段。

    【讨论】:

    • 为什么重启应用会导致准备好的语句被重新解析(并且解释计划被更新)?
    • 因为preparedStatement 是Oracle 中的一个游标,并且Oracle 知道您的应用程序会一直保持在该游标上,直到您关闭preparedStatement 或您的会话结束。通过终止应用程序来结束会话通常是唯一的控制方法。一旦您不持有该游标(应用程序重新启动后),Oracle 将注意到新索引已使共享池中的语句无效,并重新解析/重新优化该语句。请参阅此处第 3 页的流程图:oracle.com/technology/books/pdfs/jdbc_ch5.pdf
    • 删除了我的最后一条评论.. 好的.. 似乎正在发生的事情是我启动他的应用程序并且查询很快.. 但随后它变慢并且不再使用索引。为什么会这样?没有添加数据?
    【解决方案2】:

    您应该重新收集有关表格的统计信息。您可以计算或估计统计数据。示例用法

    计算

    BEGIN
      SYS.DBMS_STATS.GATHER_TABLE_STATS (
          OwnName        => 'ENROLLMENT'
         ,TabName        => 'STUDENTS'
        ,Estimate_Percent  => 0
        ,Degree            => 4
        ,Cascade           => TRUE
        ,No_Invalidate     => FALSE);
    END;
    /
    

    注意 cascade 参数告诉 oracle 也收集表上任何索引的统计信息。

    估计

    BEGIN
      SYS.DBMS_STATS.GATHER_TABLE_STATS (
          OwnName        => 'ENROLLMENT'
         ,TabName        => 'STUDENTS'
        ,Estimate_Percent  => DBMS_STATS.AUTO_SAMPLE_SIZE
        ,Degree            => 4
        ,Cascade           => TRUE
        ,No_Invalidate     => FALSE);
    END;
    /
    

    GATHER_TABLE_STATS docs

    【讨论】:

    • 谢谢,这确实有效.. 收集统计数据究竟意味着什么?为什么我需要这样做?
    • +1 给布赖恩,我今天才遇到这个!很生气,我很棒的新索引没有被使用:/ Ran stats on table and index,它起作用了。 Marcus、表和索引统计帮助优化器建模执行查询的最佳方式。通常作业在晚上运行以更新统计信息(10g,11g),但您希望尽快重新收集,以便优化器立即获得信息。有整本书专门讨论这个问题,所以我不会在这里涵盖我的 500 个字符中的所有内容。 Jonathan Lewis 撰写的“基于成本的 Oracle 基础知识”可能是深入了解的最佳起点。
    • 这改变查询性能的原因可能是它使游标无效,而不是因为新索引对优化器“不可见”。表上的统计信息不应该改变,并且拥有新索引的统计信息主要会影响表上其他索引的选择。
    • 可能两者兼而有之。取决于用于收集状态的参数。如果以前没有收集新索引中列的统计信息(例如,您使用 FOR ALL INDEXED COLUMNS),那么数据库可能没有足够的数据来决定何时最好使用索引。再次收集统计数据可以解决这个问题。至少,如果你创建一个索引,那么做一个 GATHER_INDEX_STATS
    【解决方案3】:

    Shared pool 不用于缓存数据。

    Oracle Server 有两个性能度量,逻辑读取和物理读取。物理读取是磁盘读取性能的度量。逻辑读取是从内存中读取数据的度量。

    在任何读取方法(索引、全表扫描等)中,必须将块中的行检索到缓冲区缓存中。这是物理阅读的动作。

    逻辑读是命中后从缓存返回结果,如果使用索引来提高SQL性能,就是逻辑读的提高。

    所以简而言之,没有必要。

    【讨论】:

    • 是的,共享池不缓存数据;但在这种情况下,问题是查询计划正在被缓存,并且 is 在共享池中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-06
    • 2011-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-09
    相关资源
    最近更新 更多