4

多対 1 の関係を持つ 2 つのテーブルがあります。(オラクル)

**Table: PARENT**
Field: A (PK)
Field: B
Field: C1
Field: C2
Field: C3
Field: C4
Field: C5

**Table CHILD**
Field: A (PK) (FK to PARENT.A)
Field: D (PK)
Field: E

子テーブルと親テーブルに挿入されたレコードは同時に挿入されます。

私が疑問に思っているのは、これを行う最も効率的な方法は何ですか。

現在、この挿入ステップ全体で呼び出し側アプリケーションによって呼び出されるストアド プロシージャが 1 つあります。ストアド プロシージャには現在、次のシグネチャがあります。

Field: A
Field: B
Field: C (dilimited string)
Field: D (dilimited string)
Field: E (dilimited string)

このプロシージャは、入力から C をループし、各値を配列に格納します。次に、その配列を入力からの A および B と共に使用して、表 PARENT に挿入します。

次に、入力から A を使用し、入力から D と E をループして、区切り文字列の各項目に対してテーブル CHILD に挿入します。

これは、1 日あたり最大 300 万回呼び出されます。可能な限り効率的である必要があります。

1 つだけではなく複数の SP 呼び出しを行うと、どの程度効率が失われますか?

制限された文字列を処理するためのすべてのループは、大変な作業のように思えます。

呼び出し元のアプリケーションは、CHILD へのエントリごとに個別の SP 呼び出しを行うことができると考えていました。ただし、どのようにして CHILD への挿入が PARENT への挿入の前に行われないようにするにはどうすればよいですか? (多くの場合、挿入する子レコードはありません。ある場合、通常は 10 未満ですが、50 にもなる可能性があります)

また、dilimted 文字列 C で情報を取得する別の方法も開きます。

分割された文字列から情報を取得するために while ループよりも効率的なものはありますか?

私は SP を書きませんでした。小さな変更を加えて、可能であればより効率的にするように依頼されました。

何か案は?

ノート:

テーブルを単純化しました。実際には、拡張された文字列 C には 5 ではなく 10 の項目があり、テーブル PARENT に挿入される C のような拡張された文字列がさらに 2 つあります。テーブルには、示されている以外にもいくつかのフィールドがあります

記録は 30 日後に削除されます。

4

2 に答える 2

1

ここにはいくつかのことがあります....

まず、区切り文字列をループして同様のアイテムを同様の列に配置する場合は、テーブルをリファクタリングしてより正規化する必要があります。たとえば、Cが電話番号の区切りリストで、列がC1-である場合、別の子テーブルが必要になる可能性があります。これはユースケースに依存しますが、潜在的な将来の問題(つまり、区切り文字の知識)として私を襲います。区切られた文字列に類似していないデータ (電話番号、都市、名前など) が含まれている場合は、個別のデータ要素ごとに個別のエントリ パラメータを作成してください。これは、さらに大きな潜在的な問題です (エントリの順序が重要な場合、あなたはうんざりするからです)。C5phone1phone5phone

そうです、区切られた文字列をループするのは大変な作業です。splitRDBMS になんらかの組み込み関数または何かがある場合 (または外部関数を呼び出すことができる場合) を除いて、必ずしもこれより良い方法があるとは限りません。できれば避けて、childストアドプロシージャを呼び出します。それは子供ごとに行わなければならないでしょうが、それは実際にはとにかく優れています-必ずしもパフォーマンスが賢明というわけではありませんが、それを概念化し、将来のメンテナンスのために.

childなしで行が挿入されないようにする方法はparent?外部キー制約を使用します。制約に違反している場合、それは DB ではなく呼び出し元の責任です。

さて、これらのいくつかは SP に大きな変更を加える必要があり、いくつかは基礎となるテーブル構造に変更を加える必要があります (最初に正しく設定されていれば、ユーザーに対してほとんど透過的であるはずです)。しかし、これは私が試みたであろうことです...

ああ、これはすべてコミットメント制御の下で実行されていることを教えてください...

于 2011-08-30T19:41:39.600 に答える
0

これを処理する最も効率的な方法は、ユーザー定義のデータ型を使用して、値のリストを区切り文字列ではなく配列としてストアド プロシージャに渡すことです。このようなもの:

CREATE TYPE r_child IS OBJECT
   (a NUMBER, d VARCHAR2(20), e VARCHAR2(20));

CREATE TYPE nt_child AS TABLE OF r_child;

CREATE TYPE nt_c AS TABLE OF VARCHAR2(20);

CREATE PROCEDURE insert_data(
   p_a NUMBER, p_b VARCHAR2, p_c nt_c,
   p_child nt_child
) AS
   v_parent   parent%ROWTYPE;
   i          NUMBER;
BEGIN
   v_parent.a   := p_a;
   v_parent.b   := p_a;

   FOR i IN p_c.FIRST .. p_c.LAST LOOP
      CASE i
         WHEN 1 THEN
            v_parent.c1   := p_c(i);
         WHEN 2 THEN
            v_parent.c2   := p_c(i);
         WHEN 3 THEN
            v_parent.c3   := p_c(i);
         WHEN 4 THEN
            v_parent.c4   := p_c(i);
         WHEN 5 THEN
            v_parent.c5   := p_c(i);
      END CASE;
   END LOOP;

   INSERT INTO parent(
                         a,
                         b,
                         c1,
                         c2,
                         c3,
                         c4,
                         c5
              )
   VALUES     v_parent;

   FORALL i IN p_child.FIRST .. p_child.LAST
      INSERT INTO child(
                           a, d, e
                 )
      VALUES     (
                     p_a, p_child(i).d, p_child(i).e
                 );
END insert_data;

パッケージが適切に設計されていれば、挿入をパッケージにラップしても、実行時間が大幅に増加することはありません。forallこれには、データをエンコードおよびデコードするのではなく (区切り値で現在行っているように) 、一括挿入 (私が使用した場所で示したように) を使用し、データベースが自然に読み取ることができるデータ構造を使用することが含まれます。

于 2011-08-31T15:47:45.160 に答える