web-dev-qa-db-ja.com

文字列のリストを単一のデータベースフィールドに格納することは悪い考えですか?どうして?

最近、いくつかのレガシーシステムに取り組み始めました。それを開発した人々は、データベーステーブルの単一のフィールドに文字列のリストを格納するというアイデアを思いつきました。これは、データベースに表現もデータもないオブジェクトの識別子であるとしましょう。その識別子の範囲は、本番環境では比較的小さくなります。

一方、私の直感と「良いデザインの好み」は、別のテーブルで表現する必要があることを示しています(多対多の関係を表すために使用されるテーブルと同様)。

彼らのアプローチは本当に悪いのですか?リファクタリングを開始する方が良いでしょうか?はいの場合、元の設計が将来どのような悪影響をもたらす可能性がありますか?そのアプローチを説明するリレーショナルデザインの原則はありますか?

コメントへの応答を編集:

おそらく、彼らはこのアプローチを使用して、階層構造化などの特定の問題を巧妙な方法で解決していません。最もありそうなシナリオは、彼らが時間のプレッシャーの下で単に働いていて、新しい機能をできるだけ早く実装する必要がある場合でした。

以前はフィールドが単一の値を表していたと思います。彼らは複数の値を保存する機能を実装する予定で、データベースの移行を回避しようとしました。

13
mpasko256

データモデルは正規化されていません。そうするためには、別のテーブルが必要になります。その点で、それは特に優れたデータモデリング手法ではありません。

それが正当な理由で行われたかどうかを判断することは困難です。おそらく、コーディングの簡素化またはパフォーマンスが動機であった可能性があります。おそらく、フィールドには元々1つの識別子が含まれていたため、要件が変更され、開発者はリファクタリングする時間や傾向がありませんでした。

おそらくもっと重要なのは、自分でリファクタリングするべきかどうかです。同様の状況では、デフォルトでこのようなケースを事前にリファクタリングしません。次のいずれかが当てはまる場合、私はそれを検討します。

  1. これが問題を引き起こすという証拠があります。従来の問題ログから
  2. あなたはその領域で機能的な変更を行うことを知っています
  3. データを処理するコードは特に複雑で、推論が困難です。

私がやろうとしていること、およびTBHレガシーアプリケーションを引き継ぐときはいつでもこれをお勧めします。これはwiki(または同等のもの)を開始し、このようなケースを文書化することです。たとえば、

  • データモデリングのしわなど、見つけた問題
  • 実装する予定の変更
  • 実装する予定はありませんが、時間があれば変更します
  • 推論するのが難しいコードの領域
  • 維持するのが難しいコード領域。

これは、コードベースで作業したり、コードベースに戻ったりするときに役立つ助手メモであることがわかりました。また、後継者がコードベースの学習を開始する必要があるときに、後継者にとって非常に役立ちます。

16
Alex

文字列のリストを単一のデータベースフィールドに格納することは悪い考えですか?

これは通常、正規化違反と見なされます。

ただし、これは問題の解決策として使用されることがあります。階層構造では、ある種の可変長パス文字列が構造を表します。

単一の文字列内のアイテムのリストに関する問題には、次のものがあります。

  • クエリでは、これはリレーショナル計算の代わりに文字列検索を使用することを意味します。データのインデックス作成には問題がある場合があります。
  • リスト内のエントリの順序付けの意味についての質問があります。おそらく、DBの制約として順序付けを強制することはできません。
  • 区切り文字の問題と、個々のアイテムでの文字のエスケープ/エスケープ解除の問題の可能性があります。
  • 同じリスト内のエントリが重複する可能性があります。繰り返しになりますが、これは制約を直接適用できないことに起因します(トリガー関数が制約をチェックする可能性があります)。
  • 単一のアイテムだけでもリストですが、データベースに真のタイプがリストであることを伝える(または尋ねる)ことができないため、そうではない可能性があります。ほとんどの行がリストに1つだけの項目を持っている場合、一部の行に複数の項目がある場合、これは問題になる可能性があります。列をリストとして適切に使用することを強制する方法はありません。
10
Erik Eidt

これを行うのが一般的なアンチパターンです。

要件が変化し、かつては1つしか必要でなかった場所に、より多くの値が必要になりました。本のように、著者は1人だけですよね?本に複数の著者がいると誰が推測したでしょうか?これは、データベーススキーマを変更せずに、この要件の変更を満たす簡単な方法です。

しかし、いくつかの欠点もあります。

  • 1つのフィールドに結合された識別データがあるため、クエリはより困難になります。
  • "="は使用できなくなりましたが、 "like"などを使用する必要があります。パフォーマンスが低下します。
  • そのフィールドに参加する能力を失います。
  • カウント/合計などを試してください、それは動作しません。
  • 更新すると、ぎこちなくなります。
  • コンマ区切りのリストを保持するためにvarchar(10)を選択したため、人工的な制限のようになります。
  • もっと。

したがって、基本的には、これを行わないでください。

基本的には、「リレーショナルデータベース」の「リレーショナル」を取り出します。

3
Pieter B

私たちが悪い考えであるという議論はすでにたくさんあります。それが良い、または少なくともOKなアイデアである理由をいくつか追加するのは公平だと思います。これらのうちいくつが特定のケースに当てはまるかはわかりませんが、少なくとも実行されたパフォーマンスの注釈が関連しているようです。

  • 文字列の数と長さが厳密に制限されている場合は、パフォーマンスの違いはごくわずかです。少なくとも一部のEdgeケースでは、結合が必要ないため、パフォーマンスが向上します。
  • フィールドの主な用途によっては、このフォームの方が扱いやすい場合があります。
  • リストが順序付けられていて、データに外部キーが必要ない場合、リストフィールドは、この点に関してリレーショナルデータベースが提供できるものよりもはるかに優れています。
  • 既存の特異なフィールドを単純にピギーバッキングすることは、スキーマの移行にコストがかかるシステムでは賢明な選択かもしれません。それは確かに技術的な負債ですが、かもしれません今あなたがいくつかの興味を出血させ、その後。

リファクタリングを試みるときは、常に以前の設計選択の背後にある理由を最初に理解することを常にお勧めします。条件と要件が実際に十分に変更されて、コストとリスクを正当化できることを確認してください。

0
Frax