2017-02-22 24 views
0

これは、テーブルに数百万のレコードを挿入することを意味します。私はループを使ってデータを挿入する方法を知っていますが、何百万ものデータを挿入するには良いアプローチではありません。oracleでバルク挿入を実行する最良の方法は何ですか?

私は2つのテーブル

CREATE TABLE test1 
    (
    col1   NUMBER, 
    valu   VARCHAR2(30), 
    created_Date DATE, 
    CONSTRAINT pk_test1 PRIMARY KEY (col1) 
) 
/
CREATE TABLE test2 
    (
    col2   NUMBER, 
    fk_col1  NUMBER, 
    valu   VARCHAR2(30), 
    modified_Date DATE, 
    CONSTRAINT pk_test2 PRIMARY KEY (col2), 
    FOREIGN KEY (fk_col1) REFERENCES test1(col1) 
) 
/

を持って、ループせずに100万件までいくつかのダミーレコードを挿入する方法を提案してください。

+2

何百万という行のデータソースとは何ですか? –

+1

ダミーレコードはどのくらいランダムで、どれくらい現実的である必要がありますか?子供の変更日が作成日より後でなければならない場合、いくつかのデータがnullでなければならない場合比例)など?両方のテーブルのダミー行を作成するのはかなり簡単です。あなたが実際に模擬している実際のデータの代表を作ることはやっかいです。 –

+0

コメントをいただきありがとうございます。私たちはページネーションと負荷テストをテストするためにこれを必要としています。意味のあるデータがほしいとは思いません。親テーブルと5つの子テーブルが添付されています。当分の間十分なテーブル構造を知ってもらいましょう。 –

答えて

2

あなたのコメントに基づいて十分である可能性があるかなり単純なアプローチとして、a hierarchical queryを使用してダミーデータを生成することができます。ここでは、バインド変数を使用して作成される数を制御し、ロジックの一部をやや明確にしますが、代わりにリテラルを使用できます。

まず、親行:

のような行を生成することがあります
var parent_rows number; 
var avg_children_per_parent number; 
exec :parent_rows := 5; 
exec :avg_children_per_parent := 3; 

-- create dummy parent rows 
insert into test1 (col1, valu, created_date) 
select level, 
    dbms_random.string('a', dbms_random.value(1, 30)), 
    trunc(sysdate) - dbms_random.value(1, 365) 
from dual 
connect by level <= :parent_rows; 

:親のために生成された範囲内のランダムなfk_col1

 COL1 VALU       CREATED_DA 
---------- ------------------------------ ---------- 
     1 rYzJBVI      2016-11-14 
     2 KmSWXfZJ      2017-01-20 
     3 dFSTvVsYrCqVm     2016-07-19 
     4 iaHNv       2016-11-08 
     5 AvAxDiWepPeONGNQYA    2017-01-20 

を次に子行、:

-- create dummy child rows 
insert into test2 (col2, fk_col1, valu, modified_date) 
select level, 
    round(dbms_random.value(1, :parent_rows)), 
    dbms_random.string('a', dbms_random.value(1, 30)), 
    trunc(sysdate) - dbms_random.value(1, 365) 
from dual 
connect by level <= :parent_rows * :avg_children_per_parent; 

生成される可能性があります:

select fk_col1, count(*) from test2 group by fk_col1 order by fk_col1; 

    FK_COL1 COUNT(*) 
---------- ---------- 
     1   1 
     2   3 
     3   3 
     4   7 
     5   1 

が、代わりに百万行を挿入するだけでバインド変数を変更するには:子どもの数はそれぞれの親のために異なる

select * from test2; 

     COL2 FK_COL1 VALU       MODIFIED_D 
---------- ---------- ------------------------------ ---------- 
     1   2 AqRUtekaopFQdCWBSA    2016-06-30 
     2   4 QEczvejfTrwFw     2016-09-23 
     3   4 heWMjFshkPZNyNWVQG    2017-02-19 
     4   4 EYybXtlaFHkAYeknhCBTBMusGAkx 2016-03-18 
     5   4 ZNdJBQxKKARlnExluZWkHMgoKY  2016-06-21 
     6   3 meASktCpcuyi     2016-10-01 
     7   4 FKgmf       2016-09-13 
     8   3 JZhk       2016-06-01 
     9   2 VCcKdlLnchrjctJrMXNb   2016-05-01 
     10   5 ddL       2016-11-27 
     11   4 wbX       2016-04-20 
     12   1 bTfa       2016-06-11 
     13   4 QP        2016-08-25 
     14   3 RgmIahPL      2016-03-04 
     15   2 vhinLUmwLwZjczYdrPbQvJxU  2016-12-05 

子供と保護者の関係がさらに必要な場合、たとえば変更された日付は常に作成された日付の後にあるので、あなたはクエリを変更することができます。例えば:

insert into test2 (col2, fk_col1, valu, modified_date) 
select * 
from (
select level, 
    round(dbms_random.value(1, :parent_rows)) as fk_col1, 
    dbms_random.string('a', dbms_random.value(1, 30)), 
    trunc(sysdate) - dbms_random.value(1, 365) as modified_date 
from dual 
connect by level <= :parent_rows * :avg_children_per_parent 
) t2 
where not exists (
    select null from test1 t1 
    where t1.col1 = t2.fk_col1 and t1.created_date > t2.modified_date 
); 

また、(私は列名が「日付」ではない「日時」であることに基づいて、trunc()呼び出しを介して真夜中にすべてを設定する)非真夜中の時間をすることができ、またはいくつかの列はNULL値。だからこれはちょうどあなたの出発点かもしれません。

+1

そしておそらくAPPENDヒントを投げます;).../* + APPEND * /をテストに挿入します... – BobC

+0

hmm ...どのように私はdbms_random ...を忘れてしまいましたか?それはいくつかの選択と挿入に似ているので、より多くの思考を挿入するつもりだ...私は私の観察と戻ってあなたを戻すことができます...あなたがこれは確かに私を助けるおかげで:) –

関連する問題