13

全文検索を利用するために、最近 Rails アプリを PostgreSQL に移行しました。

移行は新しいウェブホストへの移行と同時に行われたため、移行の手順は次のとおりです。

  1. 適切な database.yml ファイルを使用して、アプリケーションと db:create/db:schema:load を新しいサーバーにデプロイします。
  2. 既存の MySQL 本番データベースからの mysqldump データのみ
  3. データを PostgreSQL データベースにインポートする

アプリケーションは正常に実行されていますが、データベースに新しいコンテンツを追加しようとすると問題が発生します。たとえば、rake タスクを実行して Twitter フィードを更新すると、次のようになります。

PG::Error: ERROR:  duplicate key value violates unique constraint "twitter_feeds_pkey" DETAIL:  Key (id)=(3) already exists.

これは、新しい記事やユーザーなどを作成する他のすべてのモデルでも発生します。開発中、挿入ステートメントを n+1 回投稿すると、エラーなしでレコードが正常に保存されることがわかります。

私の質問は次のとおりです。PostgreSQL に、既存のデータから順番にインデックスを追加し始めるように指示するにはどうすればよいですか?

私はREINDEXページを読みましたが、それが本当に私が探している操作ではないと思います.

4

4 に答える 4

31

Railsでは、コマンドを使用できます

ActiveRecord::Base.connection.reset_pk_sequence!('users')

User テーブルの主キー インデックスを再度同期します。

于 2014-06-02T16:11:37.367 に答える
21

スキーマにシリアル列またはシーケンス列が含まれている場合は、これらを対応する列で発生する最大値にリセットする必要があります。(通常、シリアル番号をファイルからインポートするべきではありませんが、自動インクリメントの自由を与えてください。)

インポートされたすべてのテーブルについて、シーケンス フィールドを特定し、それらに対して次のコードを実行する必要があります。(「sch」はスキーマ名、「mytable」はテーブル名、「id」は ID カラム名に置き換えてください)

WITH mx AS ( SELECT MAX(id) AS id FROM sch.mytable)
SELECT setval('sch.mytable_id_seq', mx.id) AS curseq
FROM mx
        ;
于 2012-12-02T14:46:40.797 に答える
5

すべてのシーケンスが関連する列の現在の最大値と同期されるように、wildplasser のソリューションを自動化できます。

do
$block$
declare 
  r        record;
  stmt     text;
  max_id   integer;
begin
  for r in (
              select *
              from (
                select table_schema, 
                       table_name, 
                       column_name, 
                       pg_get_serial_sequence(table_schema||'.'||table_name, column_name) as col_sequence
                from information_schema.columns
                where table_schema not in ('pg_catalog', 'information_schema')
              ) t
              where col_sequence is not null
        ) 
  loop
    stmt := 'select coalesce(max('||r.column_name||'), 0) + 1 from '||r.table_schema||'.'||r.table_name;
    execute stmt into max_id;
    raise notice 'Next ID for %.%.% is %', r.table_schema, r.table_name, r.column_name, max_id;
    perform setval(r.col_sequence, max_id); 
  end loop;
end;
$block$

これは、列が として定義されているか、シーケンスの「所有者」になっている場合にのみ機能することに注意してserialくださいbigserial

于 2012-12-02T15:35:11.700 に答える
0

もう 1 つの方法は、列から主キー (id) を削除する (または id をダンプしない) ことです。したがって、データは次のようになります

INSERT INTO book (name, price) VALUES ('Alchemist' , 10);

それ以外の

INSERT INTO book (id, name, price) VALUES (1 , 'Alchemist' , 10);

これにより、初期データをロードした後に主キーをリセットする必要がなくなります

于 2014-05-23T17:18:10.327 に答える