Oracle sql 查询(几乎)永远运行
Posted
技术标签:
【中文标题】Oracle sql 查询(几乎)永远运行【英文标题】:Oracle sql query running for (almost) forever 【发布时间】:2010-08-19 18:41:10 【问题描述】:我的一个应用程序正在尝试执行 count(*) 查询,该查询在大约 30 分钟后返回。奇怪的是查询很简单,涉及的表很大,但并不庞大(10000条和50000条记录)。
需要 30 分钟的查询是:
select count(*)
from RECORD r inner join GROUP g
on g.GROUP_ID = r.GROUP_ID
where g.BATCH_ID = 1 and g.ENABLED = 'Y'
数据库架构本质上是:
create table BATCH (
BATCH_ID int not null,
[other columns]...,
CONSTRAINT PK_BATCH PRIMARY KEY (BATCH_ID)
);
create table GROUP (
GROUP_ID int not null,
BATCH_ID int,
ENABLED char(1) not null,
[other columns]...,
CONSTRAINT PK_GROUP PRIMARY KEY (GROUP_ID),
CONSTRAINT FK_GROUP_BATCH_ID FOREIGN KEY (BATCH_ID)
REFERENCES BATCH (BATCH_ID),
CONSTRAINT CHK_GROUP_ENABLED CHECK(ENABLED in ('Y', 'N'))
);
create table RECORD (
GROUP_ID int not null,
RECORD_NUMBER int not null,
[other columns]...,
CONSTRAINT PK_RECORD PRIMARY KEY (GROUP_ID, RECORD_NUMBER),
CONSTRAINT FK_RECORD_GROUP_ID FOREIGN KEY (GROUP_ID)
REFERENCES GROUP (GROUP_ID)
);
create index IDX_GROUP_BATCH_ID on GROUP(BATCH_ID);
我检查了数据库中是否有任何块,没有。我还运行了以下查询,除了最后两个之外的所有查询都立即返回:
select count(*) from RECORD -- 55,501
select count(*) from GROUP -- 11,693
select count(*)
from RECORD r inner join GROUP g
on g.GROUP_ID = r.GROUP_ID
-- 55,501
select count(*)
from GROUP g
where g.BATCH_ID = 1 and g.ENABLED = 'Y'
-- 3,112
select count(*)
from RECORD r inner join GROUP g
on g.GROUP_ID = r.GROUP_ID
where g.BATCH_ID = 1
-- 27,742 - took around 5 minutes to run
select count(*)
from RECORD r inner join GROUP g
on g.GROUP_ID = r.GROUP_ID
where g.ENABLED = 'Y'
-- 51,749 - took around 5 minutes to run
有人可以解释发生了什么吗?如何提高查询的性能?谢谢。
【问题讨论】:
【参考方案1】:一位同事发现了这个问题。这是因为表统计信息没有更新,并且上次分析表是几个月前(当时表基本上是空的)。我运行了分析表 RECORD 计算统计信息,现在查询在不到一秒的时间内返回。
我必须与 DBA 谈谈为什么没有更新表统计信息。
【讨论】:
现在我很生气,我没想到这一点,这在我上线期间的工作环境中多次发生在我身上。 摇头。很高兴你们想通了。 我建议你随身携带一个大的线索蝙蝠。【参考方案2】:SELECT COUNT(*)
FROM RECORD R
LEFT OUTER JOIN GROUP G ON G.GROUP_ID = R.GROUP_ID
AND G.BATCH_ID = 1
AND G.ENABLED = 'Y'
试试看,然后告诉我结果如何。不是说这就是答案,但是由于我现在无法访问数据库,因此无法对其进行测试。希望它对你有用。
【讨论】:
超过 5 分钟。 尝试用 COUNT(*) 代替 COUNT(columnName) 看看是否有任何作用。怀疑它会,但值得短暂。【参考方案3】:解释计划是一个很好的起点。
看这里:
Strange speed changes with sql query
了解如何使用解释计划语法(并查询以查看结果。)
如果这没有显示任何可疑之处,您可能需要查看痕迹。
【讨论】:
以上是关于Oracle sql 查询(几乎)永远运行的主要内容,如果未能解决你的问题,请参考以下文章