Vbulletinのバルクインポーター:relation "topics" の列 "pinned_globally" のnull値がnot-null制約に違反しています

vBulletin の一括インポーターでインポートを試みています。ほとんど完了しましたが、ユーザーと投稿は作成されたものの、トピックが作成されていません。

create_topics(topics) に渡されている内容は正しく見えます。base.rb:create_recordsprocessed 内の内容も正しく見えます(skipped は設定されていません)。しかし、トピックが作成されていません。

以下がエラーです。

ERROR:  column "pinned_globally" of relation "topics" contains null value violates not-null constraint

しかし、トピックがグローバルにピン留めされていない場合、どのような値になるべきでしょうか? base.rbTOPIC_COLUMNS でそのフィールドをコメントアウトしようとしています。

編集:これが解決策になるかもしれませんが、しばらくはわかりません。

    create_topics(topics) do |row|
      created_at = Time.zone.at(row[5])

      t = {
        imported_id: row[0],
        title: normalize_text(row[1]),
        category_id: category_id_from_imported_id(row[2]),
        user_id: user_id_from_imported_id(row[3]),
        closed: row[4] == 0,
        created_at: created_at,
        views: row[6] || 0,
        visible: row[7] == 1,
        pinned_globally: row[8] == 1 # ============== JP が追加
      }
      t[:pinned_at] = created_at if row[8] == 1

      t
    end

それは奇妙ですね。その列にはデフォルト値があるはずですが? \\d topics を実行したときに、データベースにデフォルト値はありますか?

pinned_globally | boolean | | not null | false

なるほど。それがコードにない理由だと思います。

しかし、謎は解けません。

pinned_globally    | boolean   |     | not null | false

編集:

ランダムAIによると:

これは「一括挿入ツール」かもしれません。

上記の引用が述べていることを信頼できる情報源で見つけることができませんでしたが、それは理にかなっています。この目的は速度を出すことなので、デフォルトをスキップすることは行うべきことのように思えます。そして、それは何が起こっているのかを説明しており、うまくいったことを願っている解決策でもあります。

ここに実際のドキュメントがあります! PostgreSQL: Documentation: 18: COPY

列リストが指定されている場合、COPY TO は指定された列のデータのみをファイルにコピーします。COPY FROM の場合、ファイル内の各フィールドは、指定された順序で指定された列に挿入されます。COPY FROM 列リストに指定されていないテーブル列には、デフォルト値が設定されます。

したがって、私が正しく読んでいる場合、フィールドがフィールドリストにある場合、postgres は提供されたものを盲目的にコピーし、目的のデフォルトの代わりに空白/nullが挿入されます。

どんどん遅くなっています。通常のインポーターが行っているように LIMIT 1000 を使用しない理由がありますか? 一度に 885K トピックを処理するのは多すぎるかもしれません。

前回のバルクインポートで使用したスクリプトを確認したところ、確かに明示的な pinned_globally: false が含まれており、それが不可欠であることがわかりました。これは、コード内で明示的にハードコーディングされた唯一の列値です。

    create_topics(topics) do |row|
      t = {
        imported_id: row[0],
        title: my_normalize_text(row[1]),
        category_id: category_id_from_imported_id(row[2]),
        user_id: user_id_from_imported_id(row[3]),
        created_at: Time.zone.at(row[4]),
        pinned_globally: false
      }

closedhas_summary のような、他の類似の not null, default false 列にはこのような設定がないため、奇妙です。

前回のインポートでは、バルクインポーターを使用して約2時間で300万以上のトピックを処理しました。メモリリークがあるのではないでしょうか?それとも、MySQLコード(またはソースデータを読み取るために使用しているもの)のどこかが遅いのでしょうか?

朗報です!すべてのトピックが作成されました!悪い知らせです!投稿のどれもトピックに接続されていませんが、うまくいけば、それは投稿がトピックより先に作成されたためでしょう。

それは奇妙ですね。私は説明を確信していました。 :person_shrugging:

700万件の投稿はわずか数時間しかかかりませんでしたが、100万件未満のトピックには約4時間かかりました。

それは古いマシン(明らかにその仕事のために購入したばかり?)であり、mysql はリモートです。 htop を見ても、システムレベルで明らかなメモリリークはありません。データをすべて消去し、コンテナを再構築して、今回うまくいくかどうかを確認しています。

ご協力いただき、誠にありがとうございます。

「いいね!」 1

さて、user_email のインポートが次のエラーで失敗しています。

CONTEXT:  COPY user_emails, line 1: "1  \N      @gmail.com     true    2004-03-08 14:12:00 UTC 2004-03-08 14:12:00 UTC"

さらに数時間かかりましたが、理由は次のとおりです。process_topic 関数がこれらのデフォルト値すべてを処理しています。

おそらく、次のようなものが必要だと思います。

topic[:pinned_globally] ||= false

または、おそらく

topic[:pinned_globally] ||= topic[:pinned_at].nil?
「いいね!」 1