web-dev-qa-db-ja.com

個々のインサートに対するSelectパフォーマンスの一括挿入

nodejsアプリケーションのORMとして sequelize を使用しています。

シナリオはで、PollとそのOptionsを挿入してオブジェクトを取得する必要があります。

アプローチ1:

1-Pollを挿入:

INSERT INTO `polls` (`id`,`start_at`,`expire_at`,`options_count`) VALUES (DEFAULT,1487945658,1487945965,3);

2-挿入Options(一括挿入)

INSERT INTO `poll_options` (`id`,`poll_id`,`text`) VALUES (NULL,{id},'red'),(NULL,{id},'green'),(NULL,{id},'blue');

3-Optionsを選択します(一括挿入によりidが挿入されませんOptionが得られないため、選択する必要があります)

SELECT `id`, `poll_id`, `text` FROM `poll_options` WHERE `poll_id` = {id};

アプローチ2:

1-挿入Poll

2-Optionを1つずつ挿入します(この方法でidも挿入できるので、最後に明示的なSELECTは必要ありません)

質問:

どちらのapproachが良いでしょうか?

両方のテーブルで参照整合性が有効になっていて、innodbエンジンが使用されています。

2
Shaharyar

performanceの場合、最初のアプローチの方が優れています。 これが理由です:

新しいデータがテーブルに挿入されるたびに、インデックスも更新され、物理的に並べ替えられます。 InnoDBの場合、インデックスファイルが更新されるだけでなく、データファイル自体も並べ替えられる可能性があり、主キーに基づいてclusteredになります。そのため、並べ替え/更新はコストのかかる操作であり、最小限に抑える必要があります。

一括挿入を実行すると、ステートメントが終了したときにインデックスが更新されます。つまり、すべての行を挿入した後。一方、個別に挿入すると、物理ファイルは挿入ごとに更新されます。

最初のアプローチの最後のselectステートメントのオーバーヘッドは無視できます。

2
Jehad Keriaki

あなたはORMを使用していますが、これは開発者にとってSQLの細かい詳細を隠蔽しますが、レコードと多数の詳細レコードを子テーブルに挿入するためのさまざまなアプローチに興味があるようです。

私は、意図を最も明確に伝え、より簡単に保守できるコードを選びます。私の意見では、これはおそらく2番目のオプションです。 (測定された)パフォーマンスが問題である場合にのみ、最適化を開始します。

0
Grimaldi

しかし、それらは同じではありませんか?アプローチ1は、3つのIDの1つを取得します。アプローチ2では、3つのIDをそれぞれ取得します。

そして、なぜ_poll_options_のidが必要なのですか?

これのようにあなたが必要なすべてです:

_BEGIN;

INSERT INTO `polls` (`start_at`,`expire_at`,`options_count`)
    VALUES (1487945658,1487945965,3);
-- note: no mention of polls.id, above.

{id} = LAST_INSERT_ID() -- however your language does this

INSERT INTO `poll_options` (`poll_id`,`text`)
     VALUES
     ({id},'red'),
     ({id},'green'),
     ({id},'blue');
-- again, no mention of poll_options.id

COMMIT;
_

それでも、BEGINCOMMITは実際には必要ありません。 (最悪の場合、pollsに行を格納してから、_poll_options_に行を格納できないことがあります。

パフォーマンス:

  • 1 + 1挿入は、1 + 3挿入のほぼ2倍の速度です。
  • LAST_INSERT_ID()の取得は、どのSELECTよりも高速です。
0
Rick James