0

次のうちどれがより効率的か教えてください。数千万行を処理する必要があり、パフォーマンスが重要です。

2 番目の例table0は一時テーブルで、最初の例の table0 よりもはるかに高速に作成できます。(なぜですか?) 最初の例で一時テーブルを使用できませんでした。これは、テーブルが作成される前に変数行を宣言できなかったためです。(table0元のテーブルのすべての個別の行を保持します。これは、以下のコードには示されていません。)

blah22 番目の例では、 、blah3blah4およびblah5of のハッシュ インデックスを作成することをお勧めしますがtable1、テーブルへの書き込みに時間がかかります。


FOR row IN SELECT * FROM table0
LOOP
  IF NOT EXISTS (SELECT 1 FROM table1
                   WHERE blah2 = row.blah2 AND blah3 = row.blah3
                     AND blah4 = row.blah4 AND blah5 = row.blah5) THEN
    INSERT INTO table2
      (blah0, blah1, blah2, blah3, blah4, blah5)
      VALUES (row.blah0, row.blah1, row.blah2, row.blah3, row.blah4, row.blah5);
  END IF;
END LOOP;

INSERT INTO table2
  (blah0, blah1, blah2, blah3, blah4, blah5)
  SELECT blah0, blah1, blah2, blah3, blah4, blah5 FROM table0
    WHERE NOT EXISTS
      (SELECT 1 FROM table1
         WHERE table1.blah2 = table0.blah2
           AND table1.blah3 = table0.blah3
           AND table1.blah4 = table0.blah4
           AND talbe1.blah5 = table0.blah5);
4

1 に答える 1

1

質問

2 番目の例では、table0 は一時テーブルであり、最初の例の table0 よりもはるかに高速に作成できるようです。(どうして?)

一時テーブルは通常、コンテンツがディスクに保持されないため、通常のテーブルよりもはるかに高速です。システム カタログがエントリを受け取るため、ディスクを作成するときにまだマイナーなディスク アクティビティがあります。

システムがディスクへのページのスワップアウトを開始するため、一時バッファーが不足するとすぐに一時テーブルのパフォーマンスが低下します。temp_buffersセッションの開始時に、一時テーブルにより多くの RAM を提供するように設定できます。この関連する回答の詳細。

最終的に結果をどこかに保持したい場合は、2 番目の例で通常のテーブルをすぐに使用することもできます。

個々の行をループすることは、通常、SQL コマンドを使用したセットベースの操作よりもはるかにコストがかかるため、最初の例も非常に遅くなります。

テーブルが作成される前に変数行を宣言できなかったため、最初の例では一時テーブルを使用できませんでした。(table0 は元のテーブルのすべての個別の行を保持しますが、これは以下のコードには示されていません。)

テーブルが作成される前に、関数で行タイプを使用することはできません。ただし、代わりに匿名レコードを使用できます。

DECLARE
   rec record;
BEGIN
   FOR rec IN SELECT * FROM table0 ...

代替ソリューション

しかし、あなたの最初のアプローチはとにかく良くありません。あなたの2番目のアプローチは問題ないようです。最速の方法である必要があります。別の方法は次のとおりです。

INSERT INTO table2 (blah0, blah1, blah2, blah3, blah4, blah5)
SELECT t0.blah0, t0.blah1, t0.blah2, t0.blah3, t0.blah4, t0.blah5
FROM   table0 t0
LEFT   JOIN table1 t1 USING (blah2, blah3, blah4, blah5)
WHERE  t1.t1_id IS NULL -- or any other column defined NOT NULL

(blah2, blah3, blah4, blah5)inのエントリが重複している場合はtable1、 を使用したクエリのEXISTS方がおそらく高速です。それ以外の場合は、LEFT JOIN/を使用したものIS NULLが一番上に表示される可能性があります。

インデックスとテスト

もちろん、 in のインデックスは(blah2, blah3, blah4, blah5)非常table1に役立ちます。操作を in に書き込むためのコストがいくらか追加されtable1ます。それをプレーンなbツリーインデックスにします(@Craigがコメントですでにアドバイスしているように)が、私はmulti-column indexに行きます。このケースなら安くて早い!

EXPLAIN ANALYZE@Craigがコメントでアドバイスしたように、またはEXPLAIN最初に(なしでANALYZE)パフォーマンスをテストするために使用しますEXPLAIN ANALYZE

于 2012-10-12T17:48:11.753 に答える