从非常大的表中检索大型数据集

时间:2012-12-12 05:35:09

标签: oracle plsql oracle10g

我在oracle中有一个非常大的表,包含1.4亿行。目前,我们每晚在此表上进行三次全表扫描,并使用一些结果来填充tmp表。那个tmp表然后变成了一个非常大的报告(通常是140K +行)。

大表名为tasklog,具有以下结构: tasklog_id(数字) - PK document_id(数字) date_time_in(日期) +一些不相关的行

有数百万个不同的文档ID,每个重复1到几百次,date_time_in是此条目放入数据库的时间。

所有全表扫描都是这样的

DECLARE
n_prevdocid     number;

cursor tasks is
   select * 
   from tasklog
   order by document_id, date_time_in DESC;

BEGIN

for tk in tasks
loop
    if n_prevdocid <> tk.document_id then
         -- *code snipped*

    end if;
    n_prevdocid = tk.document_id;
end loop;

END;
/

所以我的问题是:是否有一种快速(ish)方法来获取具有最新date_time_in的行的document_ids的不同列表。这可以大大加快整个过程。或者,任何人都可以想到每天检索这些数据的更好方法吗?

可能相关的事情,此表只插入了当前日期时间的行。这不是范围分区,但我看不出这对我有什么帮助。没有任何行被更新或删除。每天插入大约70k-80k行。

3 个答案:

答案 0 :(得分:1)

我认为你不会放弃至少进行一次全表扫描,因为唯一有效的方法是,如果不同document_id与总记录的比例非常小。由于生成和插入数据的方式,document_id上的聚类将非常糟糕。

怎么样:

create table tmp nologging compress -- or pctfree 0
as
select ...
from   (
  select t.*,
         max(date_time_in) over (partition by document_id) max_date_time_in
  from   tasklog t)
where   date_time_in = max_date_time_in

可能,创建一次之后,您可以通过合并到此集中仅优化更新的记录来优化进一步的刷新。有点像...

merge into tmp
using (
  select ...
  from   (
    select t.*,
           max(date_time_in) over (partition by document_id) max_date_time_in
    from   tasklog t
    where  date_time_in > (select max(date_time_in) from tmp))
  where   date_time_in = max_date_time_in)
on ... blah blah

答案 1 :(得分:0)

你试过了吗?

select document_id
from tasklog t1
where date_time_in = (select max(date_time_in)
                      from tasklog t2
                      where t1.document_id=t2.document_id)

答案 2 :(得分:0)

您可以这样做:

select document_id , date_time from tasklog group by date_time,document_id order by date_time desc;

通过这种方式,您可以使用最新的distinct document_id列检索date_time