Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oracle Pl/SQL拆分表_Oracle_Performance_Plsql - Fatal编程技术网

Oracle Pl/SQL拆分表

Oracle Pl/SQL拆分表,oracle,performance,plsql,Oracle,Performance,Plsql,我有一张甲骨文的桌子。我想做几个表,每个表包含这个表的1/10数据,实际上我只需要一列。我能够编写以下代码,但它似乎并不高效,因为它每次都在整个origin表中运行 declare baseObjid Number := 100; chunkSize Number; totalCount Number; begin select count(1) into totalCount from table_person; chunkSize := trunc(totalCoun

我有一张甲骨文的桌子。我想做几个表,每个表包含这个表的1/10数据,实际上我只需要一列。我能够编写以下代码,但它似乎并不高效,因为它每次都在整个origin表中运行

declare
  baseObjid  Number := 100;
  chunkSize  Number;
  totalCount Number;
begin
  select count(1) into totalCount from table_person;
  chunkSize := trunc(totalCount / 10) + 1;
  for i in 1 .. 10 loop
    execute immediate 'create table table_person_' || i ||
                      ' AS (select sel.r + ' || baseObjid ||
                      ' objid,  sel.objid oldId from 
                      (select rownum r, objid from table_person order by objid) sel 
                      where sel.r > ' || (i - 1) * chunkSize || 
                      ' and sel.r <= ' || i * chunkSize || ')';
    commit;
  end loop;
end;

有没有办法让它只访问原始表一次?任何其他建议也欢迎

从一个查询填充多个表的最简单方法是INSERTALL语句

此查询将PERSON的ID拆分为十个预先创建的目标表PERSON\u 1。。通过对驾驶选择中的rownum应用一个模数,PERSON_10。您可以修改查询的投影以给出不同的标准

insert all
    when rn = 1 then into person_1 (id) values (id) 
    when rn = 2 then into person_2 (id) values (id) 
    when rn = 3 then into person_3 (id) values (id) 
    when rn = 4 then into person_4 (id) values (id) 
    when rn = 5 then into person_5 (id) values (id) 
    when rn = 6 then into person_6 (id) values (id) 
    when rn = 7 then into person_7 (id) values (id) 
    when rn = 8 then into person_8 (id) values (id) 
    when rn = 9 then into person_9 (id) values (id) 
    else into person_10 values (id) 
select id, mod(rownum,10) as rn from person;
或者,您可以通过更改WHEN条件来驱动分配,例如,将WHEN条件更改为bucket:

insert all
    when id < 1000 then into person_1 (id) values (id) 
    when id < 2000 then into person_2 (id) values (id) 
    when id < 3000 then into person_3 (id) values (id) 
    when id < 4000 then into person_4 (id) values (id) 
    when id < 5000 then into person_5 (id) values (id) 
    when id < 6000 then into person_6 (id) values (id) 
    when id < 7000 then into person_7 (id) values (id) 
    when id < 8000 then into person_8 (id) values (id) 
    when id < 9000 then into person_9 (id) values (id) 
    else into person_10 values (id) 
select id from person; 
显然,bucket可能依赖于您发布的代码中的rownum列

将表创建与数据填充分离的好处值得考虑

在您发布的代码中,如果例程中途失败,比如说无法扩展表空间,则会填充一些表并可以访问,因为DDL会提交,因此不会回滚。一旦您修复了错误的来源,您就必须在重新运行例程之前清除这些表。或者您可以更改代码并跳过这些表,但这总是有问题的,尤其是因为在运行之间源表可能会发生更改,因此最终可能会出现不一致的状态


首先创建空表提供一个可恢复的位置。INSERT ALL是一条语句,它不仅比ten SELECT更具执行力,而且意味着要么填充所有表,要么不填充任何表。

我建议改用它。请描述你想要解决的真正问题。@LukaszSzozda如果没有具体细节,很难描述整个问题。我所能说的是,这些原始表是相当大的2000000行,我只需要这些临时表一小段时间。而且,要在现有表上创建分区而不丢失数据是不容易的。看起来您还需要其他东西。我假设您想要执行:@LukaszSzozda我将研究DBMS_PARALLEL_EXECUTE。这几乎是完美的,我只需要弄清楚如何使用它创建具有唯一名称的新表。@LukaszSzozda-请记住,在推荐表分区时,分区选项是企业版的额外收费选项。它不是免费使用的,建议人们在不提示他们检查许可情况的情况下使用它,如果Oracle对他们进行审核,他们的组织将面临严重的冲击。它工作正常!我很惊讶,因为我一直认为以select方式创建表比插入快得多。请注意,如果您尝试用一个操作进行此插入,您的重做空间将被过度使用。这可能会影响您的性能。@simonare-请定义过多。记住要考虑交易性和可恢复性。我希望我能不止一次地对此进行投票。回答得好!