【问题标题】:Split data from select query and commit into temp table从选择查询中拆分数据并提交到临时表中
【发布时间】:2014-03-06 16:30:47
【问题描述】:

我有一个场景,我正在使用来自 select 语句的数据创建一个临时表。我的问题是当从 select 查询中传入的数据很大时,我遇到了内存不足的问题,导致我的查询无法给出结果。

我想知道是否有办法将一大块数据(比如每 1000 行)提交到临时表中,然后再继续下一个。

Eg:
CREATE TABLE NEW_TABLE AS
   SELECT [ column1, column2...columnN ]
   FROM EXISTING_TABLE
   [ WHERE ] <ALL CONDITIONS>

现在假设内部选择返回 100 行。我不希望一次将所有 100 行插入到 NEW_TABLE 中。我想把这个分开。我该如何有效地做到这一点?

【问题讨论】:

  • 针对大量数据运行 CTAS 时遇到的确切错误是什么?
  • @tbone 不幸的是,我没有错误日志。有人告诉我有一个内存错误,这就是我要解决的问题。我的任务是优化现有查询:(

标签: sql oracle


【解决方案1】:

如果您创建临时表,为什么不将表创建为 GLOBAL TEMPORARY TABLE,像这样? :

CREATE GLOBAL TEMPORARY TABLE NEW_TABLE AS
SELECT [ column1, column2...columnN ]
FROM EXISTING_TABLE
[ WHERE ] <ALL CONDITIONS>
ON COMMIT DELETE ROWS;

由于“重做生成减少,根据定义,它们是非日志记录。”(http://psoug.org/reference/gtt.html

详细说明我写的内容:

"重做记录缓存在一个 重做日志中的循环方式 SGA 的缓冲区(请参阅“Oracle 如何 数据库写入重做日志") 并写入其中一个重做 日志写入器 (LGWR) 的日志文件 数据库后台进程。” - docs.oracle.com/cd/B28359_01/server.111/b28310/onlineredo001.htm

使用全局临时可以避免多余的内存成本。我认为您不关心安全临时数据。此外,全局临时表默认写入临时表空间,该表空间针对临时数据的存储进行了优化。

" 当Oracle需要在全局临时表中存储数据或为hash join构建hash表时,如果涉及的数据量足够小,Oracle也会在内存中启动操作并完成任务而不写入磁盘。虽然填充全局临时表或构建散列不是排序操作,但我们将在本文中将所有这些活动集中在一起,因为 Oracle 以类似的方式处理它们。

如果一个操作用尽了阈值的内存量,那么 Oracle 会将操作分成更小的操作,每个操作都可以在内存中执行。部分结果被写入磁盘的临时表空间中。”

基于: - 您使用默认进程内存(sga,撤消)以外的其他内存区域,这在您的情况下似乎很小 - 当内存不足时 -> oracle 将数据写入磁盘

【讨论】:

  • 对不起,我不太明白。你能详细说明一下吗?
【解决方案2】:

好的。我想我有一个临时解决方案/解决我的问题:像这样:

DECLARE
    counter  number (6) := 1;
    cursor c1 is
        <select query>

         type t__data is table of c1%rowtype index by inary_integer;
         t_data t__data;

begin

   open c1;
   loop
      fetch c1 bulk collect into t_data; 
      exit when t_data.count = 0;

      for idx in t_data.first .. t_data.last loop

        insert into TEMP_ONE1 (x,y)
            values (t_data(idx).x, t_data(idx).y);
            counter := counter + 1;

         if  counter = 10000
         then
          counter := 0;
          commit;
         end if;

      end loop;

   end loop;
   close c1;

end;

您认为这是解决问题的好方法吗? (我对一小部分数据进行了查询,它确实有效)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-02-09
    • 1970-01-01
    • 1970-01-01
    • 2019-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多