0

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

1)它是一个遗留系统。

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

3) 对这些表的搜索操作需要 5-6 分钟的时间。(像 select count(0) from xxxxx where isActive='Y' 这样的简单查询需要大约 6 分钟的时间。)当我们看到解释计划时,我们发现索引扫描正在 isActive 列上进行。

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

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

4

2 回答 2

4

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

你提到的行数没什么好担心的。如果您的应用程序在行数增加时表现不佳,那么您的系统就不是为扩展而设计的。我会使用 SQL*Trace 或 ASH 调查所有耗时过长的查询并修复它。

顺便说一句:恕我直言,您提到的任何内容都无法证明遗产一词的合理性。

问候,
罗布。

于 2012-04-18T11:45:34.600 回答
1

Just a few observations:

  1. I'm guessing that the "isActive" column can have two values - 'Y' and 'N' (or perhaps 'Y', 'N', and NULL - although why in the name of Fred there wouldn't be a NOT NULL constraint on such a column escapes me). If this is the case an index on this column would have very poor selectivity and you might be better off without it. Try dropping the index and re-running your query.

  2. @RobVanWijk's comment about use of SELECT COUNT(*) is excellent. ONLY ask for a row count if you really need to have the count; if you don't need the count, I've found it's faster to do a direct probe (SELECT whatever FROM wherever WHERE somefield = somevalue) with an apprpriate exception handler than it is to do a SELECT COUNT(*). In the case you cited, I think it would be better to do something like

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. As to partitioning - partitioning can be effective at reducing query times IF the field on which the table is partitioned is used in all queries. For example, if a table is partitioned on the TRANSACTION_DATE variable, then for the partitioning to make a difference all queries against this table would have to have a TRANSACTION_DATE test in the WHERE clause. Otherwise the database will have to search each partition to satisfy the query, so I doubt any improvements would be noted.

Share and enjoy.

于 2012-04-18T12:01:58.563 回答