インデックスを追加して変更するためにコピーする約1億行のテーブルがあります。新しいテーブルの作成にかかる時間はそれほど気になりませんが、データを挿入する前にテーブルを変更するか、最初にデータを挿入してからインデックスを追加すると、作成されたインデックスの効率が向上しますか?
インデックスを追加して変更するためにコピーする約1億行のテーブルがあります。新しいテーブルの作成にかかる時間はそれほど気になりませんが、データを挿入する前にテーブルを変更するか、最初にデータを挿入してからインデックスを追加すると、作成されたインデックスの効率が向上しますか?
回答:
データ挿入後にインデックスを作成する方が効率的です(バッチインポートの前とインポート後にインデックスを再作成することをお勧めします)。
Synteticの例(PostgreSQL 9.1、開発が遅いマシン、100万行):
CREATE TABLE test1(id serial, x integer);
INSERT INTO test1(id, x) SELECT x.id, x.id*100 FROM generate_series(1,1000000) AS x(id);
-- Time: 7816.561 ms
CREATE INDEX test1_x ON test1 (x);
-- Time: 4183.614 ms
インデックスを挿入して作成します-約12秒
CREATE TABLE test2(id serial, x integer);
CREATE INDEX test2_x ON test2 (x);
-- Time: 2.315 ms
INSERT INTO test2(id, x) SELECT x.id, x.id*100 FROM generate_series(1,1000000) AS x(id);
-- Time: 25399.460 ms
インデックスを作成してから挿入します-約25.5秒(2倍以上遅い)
行が追加された後にインデックスを作成することをお勧めします。高速になるだけでなく、ツリーのバランス調整もおそらく改善されます。
「バランシング」を編集することは、おそらくここでの用語の最良の選択ではありません。Bツリーの場合、定義によってバランスが取れています。しかし、それはBツリーが最適なレイアウトを持っているという意味ではありません。親内の子ノードの分布は不均一になる可能性があり(将来の更新でより多くのコストが発生する可能性があります)、更新中にバランシングが慎重に実行されない場合、ツリーの深さが必要以上に深くなる可能性があります。行が追加された後にインデックスが作成された場合、より適切に分散される可能性が高くなります。さらに、ディスク上のインデックスページは、インデックスが作成された後の断片化が少ない場合があります。 ここでもう少し情報
次の理由により、これはこの問題には関係ありません。
O(n*log(N))
長くなります(ここn
で行が追加されます)。ツリーの生成時間はO(N*log(N))
、これを古いデータと新しいデータに分割O((X+n)*log(N))
するO(X*log(N) + n*log(N))
と、これを単純に変換でき、この形式で、追加で何を待つかを簡単に確認できます。n
新しい行がある)にO(log(N))
は、新しい要素を追加した後、ツリーの構造を再生成するために必要な追加の時間が挿入されます(新しい行からのインデックス列、インデックスがすでに存在し、新しい行が追加されたため、インデックスをバランスの取れた状態に再生成する必要があります構造、このコスト指数電力である[索引の要素])。あなたは持っている新しい行が最終的にあなたが持っているその後、要約、追加の時間を。O(log(P))
P
n
n * O(log(N))
O(n*log(N))
どちらの場合も新しいデータをインデックスに挿入しているため、インデックスの効率のためにそれが本当に重要になるかどうかはわかりません。基本的に、サーバーは、インデックスが作成されるまで、インデックスがどの程度不均衡になるかを知りません。速度的には、明らかに、インデックスなしで挿入を行います。