我有一个关于在sql中构造查询的一般性问题。我有一个数据库,我需要拉过去n天的数据,结果是巨大的,以适应内存。我有个问题
SELECT * FROM DB_A WHERE data >=n days
SELECT * FROM DB_A
WHERE data >=n days
将查询适配到内存中的最佳方法是使用循环,这样我就可以每次提取m天的数据(其中m<<n)那我怎么做呢?我一点也不知道。
jmo0nnb31#
如果您使用的是oracle 12c或更高版本,则可以按如下所示使用偏移量和获取来直接使用分页:
SELECT * FROM DB_A WHERE data >=n daysORDER BY nOFFSET m*x rowsfetch next m rows only;
ORDER BY n
OFFSET m*x rows
fetch next m rows only;
这里,x是迭代次数,从0开始。假设一次需要5行。对于第一次迭代:
OFFSET 0 rowsfetch next 5 rows only;
OFFSET 0 rows
fetch next 5 rows only;
对于第二次迭代:
OFFSET 5 rowsfetch next 5 rows only;
OFFSET 5 rows
一直到最后。。。。。
cu6pst1q2#
如果数据量太大,无法作为一个整体进行处理,请在分界日期上循环说明:
SELECT * FROM DB_A WHERE date_column >= DATE_FROM and date_column < DATE_TO
WHERE date_column >= DATE_FROM and date_column < DATE_TO
请注意,性能(即内存消耗)不仅与结果行的数量有关,还与处理数据的方式有关。尽量避免在大容量数据上出现游标循环。首选的处理方式不是逐行,而是面向集合的,即。
INSERT .... SELECT .... FROM DB_A WHERE ...
如果源表 DB_A 在相关的日期列上分区( date_column 在上面的查询中)。查询将只选择那些日期受限的分区。您可以从并行dml中获益(同时使用sql方法)来提高性能。例子假设这张table DB_A 列中包含30天的数据 date_column 你想在5天内分批处理数据。您将以6个批次结束,如下面的查询所示。查询首先从表中选择不同的截断天数,然后计算 batch_idx 使用 ROW_NUMBER 除以5 trunc . 最后,边界日期为 batch_idx 是经过计算的。
DB_A
date_column
batch_idx
ROW_NUMBER
trunc
with batch1 as(select distinct trunc(date_column) start_date from db_a),batch2 as (select start_date, trunc((row_number() over (order by start_date)-1) / 5) as batch_idxfrom batch1)select batch_idx, min(START_DATE) START_DATE, max(START_DATE)+1 END_DATE from batch2group by batch_idxorder by 1; BATCH_IDX START_DATE END_DATE ---------- ------------------- ------------------- 0 01.05.2020 00:00:00 06.05.2020 00:00:00 1 06.05.2020 00:00:00 11.05.2020 00:00:00 2 11.05.2020 00:00:00 16.05.2020 00:00:00 3 16.05.2020 00:00:00 21.05.2020 00:00:00 4 21.05.2020 00:00:00 26.05.2020 00:00:00 5 26.05.2020 00:00:00 31.05.2020 00:00:00
with batch1 as
(select distinct trunc(date_column) start_date from db_a),
batch2 as (
select start_date,
trunc((row_number() over (order by start_date)-1) / 5) as batch_idx
from batch1)
select batch_idx, min(START_DATE) START_DATE, max(START_DATE)+1 END_DATE from batch2
group by batch_idx
order by 1
;
BATCH_IDX START_DATE END_DATE
---------- ------------------- -------------------
0 01.05.2020 00:00:00 06.05.2020 00:00:00
1 06.05.2020 00:00:00 11.05.2020 00:00:00
2 11.05.2020 00:00:00 16.05.2020 00:00:00
3 16.05.2020 00:00:00 21.05.2020 00:00:00
4 21.05.2020 00:00:00 26.05.2020 00:00:00
5 26.05.2020 00:00:00 31.05.2020 00:00:00
您可以在游标循环中使用这个查询来处理数据,如下所示。请注意 START_DATE 是包容的,但是 END_DATE 是排他性的。
START_DATE
END_DATE
BEGIN FOR cur in ( with batch1 as (select distinct trunc(date_column) start_date from db_a), batch2 as ( select start_date, trunc((row_number() over (order by start_date)-1) / 5) as batch_idx from batch1) select batch_idx, min(START_DATE) START_DATE, max(START_DATE)+1 END_DATE from batch2 group by batch_idx order by 1) LOOP dbms_output.put_line('Processing dates from '||to_char(cur.START_DATE,'dd.mm.yyyy') || ' to ' || to_char(cur.END_DATE,'dd.mm.yyyy')); insert into DB_TARGET(date_column,....) select date_column,.... from DB_A where date_column >= cur.START_DATE and date_column < cur.END_DATE; commit;END LOOP;END;/
BEGIN
FOR cur in (
order by 1)
LOOP
dbms_output.put_line('Processing dates from '||to_char(cur.START_DATE,'dd.mm.yyyy') || ' to ' || to_char(cur.END_DATE,'dd.mm.yyyy'));
insert into DB_TARGET(date_column,....)
select date_column,.... from DB_A
where date_column >= cur.START_DATE and date_column < cur.END_DATE;
commit;
END LOOP;
END;
/
循环将以预期的日期范围执行六次:
Processing dates from 01.05.2020 to 06.05.2020Processing dates from 06.05.2020 to 11.05.2020Processing dates from 11.05.2020 to 16.05.2020Processing dates from 16.05.2020 to 21.05.2020Processing dates from 21.05.2020 to 26.05.2020Processing dates from 26.05.2020 to 31.05.2020
Processing dates from 01.05.2020 to 06.05.2020
Processing dates from 06.05.2020 to 11.05.2020
Processing dates from 11.05.2020 to 16.05.2020
Processing dates from 16.05.2020 to 21.05.2020
Processing dates from 21.05.2020 to 26.05.2020
Processing dates from 26.05.2020 to 31.05.2020
2条答案
按热度按时间jmo0nnb31#
如果您使用的是oracle 12c或更高版本,则可以按如下所示使用偏移量和获取来直接使用分页:
这里,x是迭代次数,从0开始。
假设一次需要5行。
对于第一次迭代:
对于第二次迭代:
一直到最后。。。。。
cu6pst1q2#
如果数据量太大,无法作为一个整体进行处理,请在分界日期上循环说明:
请注意,性能(即内存消耗)不仅与结果行的数量有关,还与处理数据的方式有关。
尽量避免在大容量数据上出现游标循环。首选的处理方式不是逐行,而是面向集合的,即。
如果源表
DB_A
在相关的日期列上分区(date_column
在上面的查询中)。查询将只选择那些日期受限的分区。您可以从并行dml中获益(同时使用sql方法)来提高性能。
例子
假设这张table
DB_A
列中包含30天的数据date_column
你想在5天内分批处理数据。您将以6个批次结束,如下面的查询所示。
查询首先从表中选择不同的截断天数,然后计算
batch_idx
使用ROW_NUMBER
除以5trunc
. 最后,边界日期为batch_idx
是经过计算的。您可以在游标循环中使用这个查询来处理数据,如下所示。
请注意
START_DATE
是包容的,但是END_DATE
是排他性的。循环将以预期的日期范围执行六次: