90900


Oracleにて、3つのテーブルに大量insertする処理で相談です。

データは3テーブルにそれぞれMAXで３０００件がinsertされる想定なので、最大でも合計９０００レコードが増えることになります。

A_table, B_table, C_tableそれぞれに `table_id` というカラムを持たせており、insertの時に同じ値を入れたいです。この
`table_id` には `hoge_seq.nextval` で作成した数字を入れたいです。

実現方法としては、もしinsertするデータが３０００件の場合  
毎回 `select hoge_seq.nextval from dual` を実行→連番を取得

[code]

    insert into A_table (table_id) values(1)
    insert into B_table (table_id) values(1)
    insert into C_table (table_id) values(1)
    
[/code]

これを３０００回繰り返さないといけないでしょうか？

それとも `select hoge_seq.nextval from dual` 連番の取得をした後にinsertしたい件数分、数字をインクリメントさせて

[code]

    insert into A_table (table_id) values(1)....(3000)
    insert into B_table (table_id) values(1)....(3000)
    insert into C_table (table_id) values(1)....(3000)
    
[/code]

こっちの方がいいでしょうか？

DBへの負荷を考えたら後者の方がいい気がします  
しかし、後者を採用した場合万が一途中で別の機能からテーブルにinsertが走った時に同じIdのデータが存在する可能性が出てきており悩んでいます

ご回答よろしくお願いいたします


CC BY-SA 4.0
2022-09-02T05:20:21.377
90896
2022-12-14T17:40:14.090
2022-09-02T07:55:42.150
3060
30328
question
oracle
Oracleで複数テーブルに同じシーケンスをinsertする方法


シーケンスはトランザクションとは無関係に更新されるので、整合性を保つには前者以外の方法は考えられません。  
後者でやるのであれば、採番のためのテーブルを用意し、範囲が被らないよう排他制御する必要があるでしょう。


CC BY-SA 4.0
2022-09-02T08:58:14.473
90900
2022-09-02T08:58:14.473
50741
90896
answer


既に解決しているようですが、気づいた点コメント残します。

私も迷わず前者を選択します。たしかにシーケンスを使う事で多少負荷は上がりますがそれは、ユニークな番号を取得する為のコストとして割り切るしかないと考えます。  
マシンスペックにもよりますが9000レコードではこの違いを感じる事はないとおもいます。  
ただ使い方によっては、想定以上に遅くなることがありますので以下のような事は念頭に設計してみてください

  1. シーケンスのキャッシュ値をいくつにするのが適切か
  2. なるべく同時に複数セッションから取得要求のかからない設計を心がける  
同時に複数セッションから取得要求をかけるとenq: SV –
contentionという待機イベントが発生しはじめます。数万件程度ではそれほど気になりませんがそれ以上になると無視できないレベルです。

  3. RAC環境においてはシングル環境よりシーケンスの発番コストが上がります。
  4. シーケンスキャッシュ（デフォルト20）をもつOracleにおいて、複数セッションから同時にあるシーケンスを利用するのであれば時系列に番号が発番されないケースがありえます。
  5. 同時複数セッションでの利用がなくとも、複数のシーケンスキャッシュ値を定義している場合飛び番の発生は避けられない事。（エラーが発生しなくともありえます）

補足  
今回はDMLにてnextvalをする想定のようですが、Oracle12c以降のバージョンであれば自動採番機能があります。テーブルの対象カラムに自動採番機能を割り当てておけばアプリ側でnextvalする手間が省けるのでご検討ください。(但し今回のケースではこの方法は採用できません。Oracleの場合同じシーケンスを複数テーブルの自動採番機能に割り当てできないからです。）


CC BY-SA 4.0
2022-12-13T14:59:19.897
92756
2022-12-14T14:18:36.380
2022-12-14T14:18:36.380
55896
55896
90896
answer


## 回答ではありません。

例えばこんな方法で入れるのもありという内容です。

### SQL

[code]

    -- DDL
    CREATE SEQUENCE hoge_seq;
    CREATE TABLE A_table(id NUMBER PRIMARY KEY, value VARCHAR2(10));
    CREATE TABLE B_table(id NUMBER PRIMARY KEY, value VARCHAR2(10));
    CREATE TABLE C_table(id NUMBER PRIMARY KEY, value VARCHAR2(10));
    CREATE TABLE tmp_to_insert(aval VARCHAR2(10), bval VARCHAR2(10), cval varchar2(10));
    
    -- データロードは適当なツール(sql loaderの最速オプション指定など)でtmp_to_insertに突っ込む。ココでは普通に入れる。
    insert into tmp_to_insert values('foo1', 'bar1', 'hoge1');
    insert into tmp_to_insert values('foo2', 'bar2', 'hoge2');
    insert into tmp_to_insert values('foo3', 'bar3', 'hoge3');
    commit;
    -- ちゃんと入ったか確認
    select * from tmp_to_insert;
    
    -- 後は流し込むだけ
    INSERT ALL
    INTO A_table(id, value) values(hoge_seq.nextval, aval)
    INTO B_table(id, value) values(hoge_seq.nextval, bval)
    INTO C_table(id, value) values(hoge_seq.nextval, cval)
    SELECT * FROM tmp_to_insert;
    
    -- 確認
    SELECT *
    FROM A_table A
        inner join B_table B on B.id=A.id
        inner join C_table C on C.id=B.id
    ;
    commit;
    
    -- 後始末
    drop table tmp_to_insert cascade constraints purge;
    
[/code]

### 実行結果

[code]

    [root@cc15414f91d5 ~]# sqlplus system/oracle@database:1521 <hoge.sql
    
    SQL*Plus: Release 21.0.0.0.0 - Production on Wed Dec 14 17:39:14 2022
    Version 21.6.0.0.0
    
    Copyright (c) 1982, 2022, Oracle.  All rights reserved.
    
    Last Successful login time: Wed Dec 14 2022 17:37:38 +00:00
    
    Connected to:
    Oracle Database 21c Express Edition Release 21.0.0.0.0 - Production
    Version 21.3.0.0.0
    
    SQL> SQL> 
    Sequence created.
    
    SQL> 
    Table created.
    
    SQL> 
    Table created.
    
    SQL> 
    Table created.
    
    SQL> 
    Table created.
    
    SQL> SQL> SQL> 
    1 row created.
    
    SQL> 
    1 row created.
    
    SQL> 
    1 row created.
    
    SQL> 
    Commit complete.
    
    SQL> SQL> 
    AVAL       BVAL       CVAL
    ---------- ---------- ----------
    foo1       bar1       hoge1
    foo2       bar2       hoge2
    foo3       bar3       hoge3
    
    SQL> SQL> SQL>   2    3    4    5  
    9 rows created.
    
    SQL> SQL> SQL>   2    3    4    5  
            ID VALUE              ID VALUE              ID VALUE
    ---------- ---------- ---------- ---------- ---------- ----------
             1 foo1                1 bar1                1 hoge1
             2 foo2                2 bar2                2 hoge2
             3 foo3                3 bar3                3 hoge3
    
    SQL> 
    Commit complete.
    
    SQL> SQL> SQL> 
    Table dropped.
    
    SQL> Disconnected from Oracle Database 21c Express Edition Release 21.0.0.0.0 - Production
    Version 21.3.0.0.0
    [root@cc15414f91d5 ~]# 
    
[/code]

※Oracle Database 21c Express Edition


CC BY-SA 4.0
2022-12-14T17:26:59.520
92790
2022-12-14T17:40:14.090
2022-12-14T17:40:14.090
54957
54957
90896
answer