ORACLE db性能调优

时间:2012-04-18 11:25:10

标签: oracle

我们遇到性能问题需要一些建议(我们在Oracle 10g R2上) 情况就像这样

1)这是一个遗留系统。

2)在某些表中,它保存了过去10年的数据(意味着自第一个版本推出以来,数据从未被删除)。现在,在大多数OLTP表中,它们有大约30,000,000 - 40,000,000行。

3)这些表上的搜索操作持续5-6分钟。 (一个简单的查询,比如来自xxxxx的select count(0),其中isActive ='Y'需要大约6分钟的时间。)当我们看到解释计划时,我们发现索引扫描发生在isActive列上。

4)我们建议归档和清除不需要的旧数据,团队正在努力解决这个问题。即使我们删除了5年的数据,我们还剩下大约15,000,000 - 20,000,000行表,这些行本身非常庞大,所以我们考虑在这些表上分配表,但我们发现用户可以搜索大部分数据。来自UI的这些表的列,因此将破坏表分区的目的。

那么需要采取哪些措施来改善这种状况。

2 个答案:

答案 0 :(得分:4)

首先:质疑您首先发出查询select count(0) from xxxxx where isactive = 'Y'的原因。十分之九是检查记录是否存在的懒惰方式。如果是这种情况,只需将其替换为选择1行的查询(rownum = 1和first_rows提示)。

您提到的行数无需担心。如果您的应用程序在行数增加时性能不佳,那么您的系统不能进行扩展。我会使用SQL * Trace或ASH调查所有花费太长时间的查询并修复它。

顺便说一下:你提到的没有任何理由证明遗产,恕我直言。

的问候,
罗布。

答案 1 :(得分:1)

只是一些观察:

  1. 我猜测“isActive”列可以有两个值 - 'Y'和'N'(或者可能是'Y','N'和NULL - 尽管为什么以Fred的名义出现不会是这样一个列上的NOT NULL约束逃避我)。如果是这种情况,此列上的索引选择性会非常差,如果没有它,您可能会感觉更好。尝试删除索引并重新运行查询。

  2. @ RobVanWijk关于使用SELECT COUNT(*)的评论非常好。如果你真的需要计算,只要求行数;如果您不需要计数,我发现使用apprpriate异常处理程序进行直接探测(SELECT whatever FROM wherever WHERE somefield = somevalue)比执行SELECT COUNT(*)更快。在你引用的案例中,我认为最好做一些像

  3. 这样的事情

    BEGIN

      SELECT IS_ACTIVE
        INTO strIsActive
        FROM MY_TABLE
        WHERE IS_ACTIVE = 'Y';
    
      bActive_records_found := TRUE;
    EXCEPTION
      WHEN NO_DATA_FOUND THEN
        bActive_records_found := FALSE;
      WHEN TOO_MANY_ROWS THEN
        bActive_records_found := TRUE;
    END;
    
    1. 关于分区 - 分区可以有效减少查询时间 IF 在所有查询中使用分区表的字段。例如,如果在TRANSACTION_DATE变量上对表进行了分区,那么为了使分区产生差异,针对该表的所有查询都必须在WHERE子句中进行TRANSACTION_DATE测试。否则,数据库必须搜索每个分区以满足查询,因此我怀疑是否会注意到任何改进。
    2. 分享并享受。