0

(tldr;定期的な更新により、テーブルは自然キーを使用するように強制されると思います。そのため、データベーススキーマを移行する必要があります。)

私は、 Planets のようなテーブルを持つ実稼働データベースを持っています。これは、潜在的な自然キー (実際には決して変化しない惑星名など) を持っていますが、典型的なインクリメントされた整数を主キーとして使用します惑星テーブルには、*parent_planet_id* などの自己参照列が 1 つまたは 2 つあります。

現在、毎週惑星レコードのサブセットを再作成するオフラインのクラウドベースのワーカーを構築しており、メイン サーバーと統合する必要があります。私の計画は次のとおりです。

  • ワーカー インスタンスにはミニ バージョンのデータベースがあります (スキーマは同じですが、Planets レコードはありません)。
  • 週に 1 回、ワーカーが起動し、すべての処理を行い、約 100,000 の惑星レコードを作成し、データをエクスポートします。(この特定の問題では、エクスポート形式は重要ではないと思います。mysqldump、yamlなどである可能性があります。)
  • 次に、運用サーバーがレコードをインポートします。一部は新しいレコードで、ほとんどは更新されています。

この最後のステップは、解決方法がわからないものです。私は毎回 Planets テーブルを完全に置き換えているわけではないので、問題は 2 つのデータベースがそれぞれ独自のインクリメント整数 PK を持っていることです。そのため、単純なインポートを行うことはできません。

id 列なしでエクスポートすることを考えましたが、自己参照列がこれを妨げていることに気付きました。

考えられる解決策は 2 つあります。

  • スキーマを再設計して、planets テーブルに自然キーを使用します。これは苦痛でしょう。
  • キーの増分整数の代わりに UUID を使用します。移動するのは簡単だと思います。ID は一意であり、新しい行は安全にインポートできます。これにより、キーの自然なデータに依存する問題も回避されます。
4

3 に答える 3

1

を変更して、ネストされたセットクロージャ テーブル、またはパス列挙Planetsなどの代替階層手法を使用し、エクスポートよりも優先します。これにより、ID 依存関係が解消されます。

または、それでもこの考えが気に入らない場合は、エクスポートとインポートを ETL の問題と考えてください。

  • エクスポート中にレコードを変更して含めるPlanetName, ParentPlanetName
  • PlanetNames最初にすべての惑星 ( )をインポートします
  • 次に、階層をインポートします ( ParentPlanetName)

いずれにせよ、最初の DB からの代理キーは決してその DB を離れてはなりません。それ以外では意味がありません。

于 2012-09-17T11:53:25.090 に答える
0

ほとんどの操作は更新です

したがって、「実際の」マージが必要です。つまり、データを挿入/更新できる適切な順序を特定する必要があるため、プロセスでFKに違反することはありません。

意味はわかりませんparent_planet_idが、「軌道」を意味し、「惑星」という単語が衛星も含むように拡張されていると仮定すると、マスターデータベースにフォボスのみがあり、火星とダイモスをインポートする必要があると想像してください。これは、特定の順序でのみ実行できます。

  1. 火星を挿入します。
  2. Deimosを挿入parent_planet_idし、火星を指すように設定します。
  3. parent_planet_id火星を指すようにフォボスを更新します。

手順(2)と(3)は交換できますが、手順(1)の前はどちらも交換できませんでした。

適切な順序を決定し、自然キー1を比較して、何を更新する必要があり、何を挿入するかを確認するには、再帰下降が必要です。残念ながら、MySQLは再帰クエリをサポートしていないため、手動で行う必要があります。

サロゲートキーがこのプロセスでどのように役立つかはよくわかりません。どちらかといえば、サロゲートキーによって、最終的に調整する必要のある間接参照のレベルがもう1つ追加されます。


1これは、サロゲートとは異なり、さまざまなデータベース間で意味があります。同じ整数値が異なるデータベース内の異なる惑星を識別する可能性があるため、自動インクリメントされた整数を単に比較することはできません-誤ったUPDATEが発生します。一方、GUIDは、行が同じ惑星を記述している場合でも一致することはありません。誤ったINSERTが発生します。

于 2012-09-17T15:31:51.560 に答える
0

(設計の観点から) 最善の解決策は、キー アーキテクチャを改良し、惑星がいつどこからインポートされたかに関する情報を持つ複合キーを実装することですが、これを行いたくありません。

より簡単に(私は思う)、それでも少し「幸せなエンジニアリング」ソリューションは、インポートキーを変更することです。たとえば、次のように実行できます。 1. メイン システムで Planets テーブルをロックする (インポート中に新しいキーが表示されないようにする) 2. メイン システムの Planet テーブルに基づいて ID と PLANET NAME の 2 つの列を持つルックアップ テーブルを作成する 3 . そのテーブルから最大のキー値を取得し、4. ステップ 3 で取得した MAX 値を追加して、インポートされたすべてのキー (親子惑星の関係を識別および参照) の値をインクリメントします。5. メインの惑星テーブルを変更し、現在の自動インクリメントを変更します。実際の MAX の値 + 1 の値 6. テーブルを調べて (プロシージャ内のカーソル ループ)、現在の惑星名に対してルックアップに異なるキーがあるかどうかを確認します。

于 2012-09-17T15:06:56.473 に答える