我们遇到性能问题需要一些建议(我们在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的这些表的列,因此将破坏表分区的目的。
那么需要采取哪些措施来改善这种状况。
答案 0 :(得分:4)
首先:质疑您首先发出查询select count(0) from xxxxx where isactive = 'Y'
的原因。十分之九是检查记录是否存在的懒惰方式。如果是这种情况,只需将其替换为选择1行的查询(rownum = 1和first_rows提示)。
您提到的行数无需担心。如果您的应用程序在行数增加时性能不佳,那么您的系统不能进行扩展。我会使用SQL * Trace或ASH调查所有花费太长时间的查询并修复它。
顺便说一下:你提到的没有任何理由证明遗产,恕我直言。
的问候,
罗布。
答案 1 :(得分:1)
只是一些观察:
我猜测“isActive”列可以有两个值 - 'Y'和'N'(或者可能是'Y','N'和NULL - 尽管为什么以Fred的名义出现不会是这样一个列上的NOT NULL约束逃避我)。如果是这种情况,此列上的索引选择性会非常差,如果没有它,您可能会感觉更好。尝试删除索引并重新运行查询。
@ RobVanWijk关于使用SELECT COUNT(*)
的评论非常好。如果你真的需要计算,只要求行数;如果您不需要计数,我发现使用apprpriate异常处理程序进行直接探测(SELECT whatever FROM wherever WHERE somefield = somevalue
)比执行SELECT COUNT(*)
更快。在你引用的案例中,我认为最好做一些像
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;
分享并享受。