web-dev-qa-db-ja.com

複数のMySQLテーブルと1つの大きなテーブルのどちらが効率的ですか?

MySQLデータベースにさまざまなユーザーの詳細を保存します。もともとはさまざまなテーブルに設定されていました。つまり、データはUserIdにリンクされ、必要に応じてデータを表示および操作するための複雑な呼び出しを介して出力されます。新しいシステムをセットアップする場合、これらすべてのテーブルを関連コンテンツの1つの大きなテーブルに結合することはほとんど意味があります。

  • これは助けになるのでしょうか?
  • 呼び出し、更新、検索/操作の速度を考慮しますか?

これが私のテーブル構造の例です:

  • ユーザー-ユーザーID、ユーザー名、メール、暗号化されたパスワード、登録日、IP
  • user_details-Cookieデータ、名前、住所、連絡先の詳細、所属、人口統計データ
  • user_activity-投稿、最後のオンライン、最後の閲覧
  • user_settings-プロファイル表示設定
  • user_interests-ターゲット設定可能な変数の広告
  • user_levels-アクセス権
  • user_stats-ヒット、集計

編集:私はこれまですべての答えを支持しましたが、それらはすべて本質的に私の質問に答える要素を持っています。

ほとんどのテーブルには1:1の関係があり、これが非正規化の主な理由です。

これらのセルの大部分が空のままになる可能性が高いときに、テーブルが100以上の列にまたがっている場合、問題が発生しますか?

95
Peter Craig

複数のテーブルは、次の方法/ケースで役立ちます。

(a)異なる人々が異なるテーブルを含むアプリケーションを開発する場合、それらを分割することは理にかなっています。

(b)データ収集のさまざまな部分について、さまざまな人にさまざまな種類の権限を付与する場合、それらを分割する方が便利な場合があります。 (もちろん、適切にビューを定義して許可を与えることを見ることができます)。

(c)特に開発中にデータを別の場所に移動する場合、テーブルを使用するとファイルサイズが小さくなります。

(d)フットプリントを小さくすると、単一のエンティティの特定のデータ収集でアプリケーションを開発する際に安心感が得られる場合があります。

(e)可能性です。単一の値のデータとして考えていたものが、将来的には本当に複数の値になる可能性があります。例えば現在、与信限度は単一の値フィールドです。しかし、明日、値を(日付から、日付から、クレジット値として)変更することを決定できます。分割テーブルが便利になりました。

私の投票は複数のテーブルに対するものです-データは適切に分割されています。

がんばろう。

59
user115905

テーブルを結合することを非正規化と呼びます。

メンテナンスヘルルを作成する代わりに、いくつかのクエリ(JOINsを大量に作成する)を高速に実行すると役立つ場合があります(またはできない場合があります)。

MySQLは、JOINメソッド、つまりNESTED LOOPS

これは、駆動テーブルの各レコードに対して、MySQLがループ内の駆動テーブルの一致するレコードを見つけることを意味します。

レコードの検索は非常にコストのかかる操作であり、純粋なレコードスキャンの数十倍の時間がかかる場合があります。

すべてのレコードを1つのテーブルに移動すると、この操作を取り除くのに役立ちますが、テーブル自体が大きくなり、テーブルスキャンに時間がかかります。

他のテーブルに多数のレコードがある場合、テーブルスキャンを増やすと、順次スキャンされるレコードの利点が過大になる可能性があります。

一方、メンテナンス地獄は保証されています。

33
Quassnoi

それらはすべて1:1の関係ですか?たとえば、ユーザーが異なるユーザーレベルに属している場合、またはユーザーの興味がユーザーの興味表の複数のレコードとして表されている場合、それらの表をマージすることは即座に問題になります。

正規化に関する以前の回答については、データベース正規化ルールはパフォーマンスを完全に無視しており、きちんとしたデータベース設計だけを検討していると言わなければなりません。それはたいてい達成したいことですが、パフォーマンスを追求するために積極的に非正規化することが理にかなっている場合があります。

全体として、質問はテーブルにあるフィールドの数と、それらにアクセスされる頻度に帰着すると思います。ユーザーのアクティビティがあまり面白くない場合は、パフォーマンスおよびメンテナンスの理由から、常に同じレコードに記録するのは面倒かもしれません。たとえば、設定などの一部のデータが非常に頻繁にアクセスされ、フィールドが多すぎる場合、テーブルをマージするのも便利ではない可能性があります。パフォーマンスの向上のみに関心がある場合は、設定を個別に保持するなど、他のアプローチを検討することもできますが、設定を独自のセッション変数に保存して、頻繁にデータベースを照会する必要がないようにします。

17
David Hedlund

allこれらのテーブルの1-to-1 関係?たとえば、各ユーザー行の対応する行はuser_statsまたはuser_levels?その場合は、それらを1つのテーブルに結合するのが理にかなっています。関係ではない1 to 1しかし、それらを結合(非正規化)することはおそらく意味をなさないでしょう。

それらを別々のテーブルと1つのテーブルに分けても、数十万または数百万のユーザーレコードがない限り、おそらくパフォーマンスにはほとんど影響しません。あなたが得る唯一の本当の利益は、クエリを組み合わせることでクエリを簡素化することです。

ETA:

懸念列が多すぎるについてである場合、通常一緒に使用してそれらを組み合わせるものについて考え、残りを別の場所に残しますテーブル(または必要に応じていくつかの個別のテーブル)。

データの使用方法を見ると、クエリの80%がそのデータの20%を使用しており、残りの80%のデータがたまにしか使用されていないことがわかります。頻繁に使用する20%を1つのテーブルに結合し、80%を別のテーブルで頻繁に使用しないようにすると、おそらく妥協が得られます。

14
Eric Petroelje

1つの大規模なテーブルを作成すると、リレーショナルデータベースプリンシパルに反します。それらすべてを1つのテーブルにまとめることはしません。繰り返しデータの複数のインスタンスを取得します。たとえば、ユーザーが3つの興味を持っている場合、3つの異なる興味を保存するためだけに同じユーザーデータを持つ3つの行があります。最終的には、複数の「正規化された」テーブルアプローチに進みます。データベースの正規化については、 this Wikiページを参照してください。

編集:あなたの質問を更新したので、私の答えを更新しました...

これらのセルの大部分は空のままになる可能性が高い

たとえば、ユーザーが関心を持っていなかった場合、正規化すると、そのユーザーの関心テーブルに行が表示されなくなります。 1つの巨大なテーブルにすべてがある場合、NULLのみを含む列(および明らかに多くの列)があります。

私は、大量のテーブルが存在する電話会社で働いており、データを取得するには多くの結合が必要になる場合があります。これらのテーブルからの読み取りのパフォーマンスが重要な場合、作成されたプロシージャは、レポートが指す結合、計算などを必要としないフラットテーブル(非正規化テーブル)を生成できます。これらは、SQLサーバーエージェントと組み合わせて使用​​され、特定の間隔でジョブを実行します(つまり、一部の統計の週次ビューが週に1回実行されるなど)。

8
user110714

同じアプローチを使用しない理由Wordpressは、すべてのユーザーが持つ基本的なユーザー情報を持つユーザーテーブルを作成し、基本的にユーザーに関連付けられた任意のキーと値のペアである「user_meta」テーブルid。したがって、ユーザーのすべてのメタ情報を検索する必要がある場合は、それをクエリに追加するだけでよく、ログインなどの必要がない場合は、追加のクエリを常に追加する必要はありません。 Twitterハンドルや個々の興味の保存など、ユーザーに新しい機能を追加するためにテーブルを開いたままにします。また、関連するIDの迷路に対処する必要はありません。 50ではなく1つの関連付けのみ。

Wordpressは特にプラグインを介して機能を追加できるようにするため、プロジェクトをよりスケーラブルにできるようにし、新しい機能を追加する必要がある場合に完全なデータベースのオーバーホールを必要としません。

7
Rudy Garcia

これは「依存する」状況の1つだと思います。複数のテーブルを用意する方がよりクリーンで、おそらく理論的には優れています。ただし、1人のユーザーに関する情報を取得するために6〜7個のテーブルを結合する必要がある場合は、そのアプローチを再考し始める可能性があります。

3
Tundey

他の表が実際に何を意味しているかに依存すると思います。 user_detailsには、さらに1人以上のユーザーが含まれますか。正規化のレベルがニーズに最も適しているのは、要求によって異なります。

適切なインデックスを持つテーブルが1つある場合は、おそらくより高速になります。しかし、他方では、おそらく保守がより困難です。

おそらくユーザーとの1対1の関係なので、User_Detailsをスキップできるように見えます。しかし、残りはおそらくユーザーごとの行の多くですか?

1
Richard L