シリアル列を使用する
あなたの計画は、4000万(!)行の不必要に巨大なインデックスを追加することです。そして、あなたはそれがユニークになるかどうかさえ確信していません。私はその行動経路に反対することを強くお勧めします。 シリアルコード>
代わりに列を作成してください:
ALTER TABLE tbl ADD COLUMN tbl_id serial PRIMARY KEY;
それはあなたがする必要があるすべてです。残りは自動的に行われます。マニュアルまたはこれらの密接に関連する回答の詳細:
C++でPostgreSQLの主キーの自動インクリメントがクラッシュする
SQL関数の自動インクリメント
シリアル
の追加 カラムは1回限りの操作ですが、コストがかかります。テーブル全体を書き直して、操作中の更新をブロックする必要があります。営業時間外に同時ロードせずに行うのが最適です。 ここのマニュアル
を引用します :
これによりテーブル全体が効果的に書き換えられるため、シリアルpk列を使用して新しいテーブルを作成し、古いテーブルからすべての行を挿入し、シリアルにシーケンスのデフォルト値を入力させ、古いものを削除して新しい名前を変更することもできます。これらの密接に関連する回答の詳細:
PostgreSQL9.2でテーブルをロックせずにデータベース行を更新する
テーブルなしで新しい列を追加ロックしますか?
すべてのINSERTステートメントにターゲットリストがあることを確認してください。そうすれば、追加の列でそれらを混乱させることはできません。
INSERT INTO tbl (col1, col2, ...) VALUES ...
ない:
INSERT INTO tbl VALUES ...
シリアル
integer
で実装されています 列(4バイト)。
主キー制約は、一意のインデックスと NOT NULL
を使用して実装されます。 関連する列に対する制約。
インデックスの内容は、テーブルのように格納されます。追加の物理ストレージは別途必要です。この関連する回答の物理ストレージの詳細:
PostgreSQLのスペースの計算と節約
インデックスには、2つのタイムスタンプ(2 x 8バイト)と長いファイル名が含まれます。パス(〜50バイト?)これにより、インデックスが約2.5 GB大きくなり(40M x 60 ..何かバイト)、すべての操作が遅くなります。
重複の処理
「重複のインポート」の処理方法は、データのインポート方法と「重複」の正確な定義方法によって異なります。
コピー
について話している場合
ステートメントの1つの方法は、一時的なステージングテーブルを使用し、単純な SELECT DISTINCT
で重複を折りたたむことです。 またはDISTINCTON
INSERT
で コマンド:
CREATE TEMP TABLE tbl_tmp AS
SELECT * FROM tbl LIMIT 0; -- copy structure without data and constraints
COPY tbl_tmp FROM '/path/to/file.csv';
INSERT INTO tbl (col1, col2, col3)
SELECT DISTINCT ON (col1, col2)
col1, col2, col3 FROM tbl_tmp;
または、既存の行との重複を禁止するには:
INSERT INTO tbl (col1, col2, col3)
SELECT i.*
FROM (
SELECT DISTINCT ON (col1, col2)
col1, col2, col3
FROM tbl_tmp
) i
LEFT JOIN tbl t USING (col1, col2)
WHERE t.col1 IS NULL;
臨時雇用者テーブルはセッションの終了時に自動的に削除されます。
ただし、適切な修正は、最初に重複を生成するエラーのルートに対処することです。
元の質問
1)すべての列に重複が1つある場合、pkをまったく追加できませんでした。
2)PostgreSQLデータベースバージョン8.1にのみ触れます 5フィートのポール付き。それは絶望的に古く、時代遅れで非効率的であり、もはやサポートされておらず、おそらく多くの未修正のセキュリティホールがあります。 公式のPostgresバージョン管理サイト。
@David
すでにSQLステートメントを提供しています。
3&4)重複キー違反。 PostgreSQLがエラーをスローするということは、トランザクション全体がロールバックされることも意味します。これをperlスクリプトでキャッチしても、残りのトランザクションを実行することはできません。たとえば、例外をキャッチできるplpgsqlを使用してサーバー側スクリプトを作成する必要があります。