【发布时间】:2016-06-02 19:02:07
【问题描述】:
我对使用 sqlplus 很陌生,所以如果这是一个愚蠢的问题,我很抱歉。
我有一个很长的表单查询:
SELECT columnA
from tableA
where fieldA in (
(select unique columnB
from tableB
where fieldB in
(select columnC
from tableC
where fieldC not in
(select columnD
from tableD
where x=y
and a=b
and columnX in
(select columnE
from tableE
where p=q)))
and columnInTableB = <some value>
and anotherColumnInTableB = <some other value>
and thirdColumnInTableB IN (<set of values>)
and fourthColumnInTableB like <some string>);
每个表大约有 15 - 30 列和不同数量的行。 TableB 是最大的,总共有大约 500 万行。表 A - E 各有 500,000 - 100 万行。
我尝试了几种方法:
1) 按原样运行此查询:
这个查询运行了很长时间,我得到了错误 - ORA-01555: 快照太旧: 回滚段号 名称为
我做了一些研究,发现如下: ORA-1555: snapshot too old: rollback segment number
但是,我没有更改撤消段的权限。
2) 我使用 with...as 重新编写了查询,但随后出现错误: 无法通过 在表空间 TEMP
中扩展临时段再次,我找到了有关如何修复此错误的说明,但我没有扩展临时段的权限。
运行时间最长的查询是:
(select unique columnB
from tableB ...
在最坏的情况下,and fourthColumnInTableB like <some string>); 匹配表 B 中大约 300 万个条目。
有人建议我“以较小的块运行查询”。
我想到的一种方法是为长时间运行的子查询检索数据(
(select unique columnB
from tableB ...
)
以块为单位(按照建议使用 ROWNUM here。 我的问题是这样的:
我不知道这个子查询有多少潜在的匹配项。我可以动态设置 ROWNUM 以分块检索数据吗?
如果是,您能否举例说明 while 循环的外观,以及如何确定结果集何时耗尽?
我为此找到的一个选项是检查while @@ROWCOUNT > 0 或使用:
while exists (query)
但是,我仍然不确定如何编写循环以及如何使用变量 (?) 来动态设置 ROWNUM。
基本上,我想知道我是否可以这样做:
SELECT columnA
from tableA
where fieldA in (
while all results have not been fetched:
select *
from
(select a.*, rownum rnum
from
(select unique columnB
from tableB
where fieldB in
(select columnC
from tableC
where fieldC not in
(select columnD
from tableD
where x=y
and a=b
and columnX in
(select columnE
from tableE
where p=q)))
and columnInTableB = <some value>
and anotherColumnInTableB = <some other value>
and thirdColumnInTableB IN (<set of values>)
and fourthColumnInTableB like <some string>) a
where rownumm <= i) and rnum >= i);
update value of i here (?) so that the loop can repeat
如何在某个循环中动态更新上面 rownum/rnum 的 'i' 的值,以检索块(例如 10000)的结果,直到结果集耗尽?
另外,while 循环应该是什么样的?
我也不知道如何使用 joins 重写它(我的 sql 知识非常有限),所以如果有人可以帮助我使用 joins 或任何其他方法更有效地重写它,那也可以。
非常感谢您对此提供的任何帮助。我已经坚持了几天了,我无法确定一个合适的解决方案。
谢谢!
【问题讨论】:
-
如果您的问题是关于 oracle 的,为什么还要标记 mysql 和 sql-server?
-
如果没有表、数据卷、查询及其执行计划的详细信息,我认为我们无能为力 - 它太笼统了。使用连接而不是子查询,并检查您的统计数据是否是最新的,是唯一跳出来的一般建议;我们不知道为什么你这样做的方式是个问题。也许您使用了旧语法并错过了连接条件。您似乎也在尝试遵循其他 RDBMS 的建议 - 将您的研究重点放在专门适用于 Oracle 的事物上。
-
如果子查询是长时间运行的位,那么您可以尝试使用
EXISTS而不是IN。来自Oracle 10.2 SQL Tuning documentation:“如果选择性谓词在子查询中,则使用IN。如果选择性谓词在父查询中,则使用 EXISTS。” -
我对其进行了编辑以添加有关表和一般查询结构的更多详细信息。希望这会有所帮助。
-
你能发一份计划吗? set linesize 180 set autotrace traceonly
标签: oracle select subquery sqlplus rownum