0

私は SQL を初めて使用し、パフォーマンスへの影響を理解していません。SQL データベースはすべてを 1 か所に格納しているようです。これは、テーブルが非常に急速に非常に大きくなることを意味しませんか? これはパフォーマンスに影響しませんか?

Stackoverflow モデルの例ですが、スレッド化されたコメントがあります。

CREATE TABLE t_users (
   name varchar(80) primary key,
   email varchar(80)

);

CREATE TABLE t_posts (
   id varchar(80) primary key,
   userid varchar(80) references t_users(name),
   title varchar(80),
   description text,
   topic varchar(80),
   path text

);

これは有効な設計ですか?これまでにすべてのユーザーのすべての投稿が同じテーブルに保存されています...したがって、トピック「プログラミング」を持つすべてのコメントを照会したい場合は、トピックが異なる投稿であっても、すべての投稿を調べる必要があります。それらはすべて同じテーブルに格納されています....これは、より複雑なクエリを作成すると、ディスク上のテーブルが大きくなるほど指数関数的に遅くなることも意味します。すべての投稿を新しいテーブルに分割したほうがよいのではないでしょうか?

4

3 に答える 3

3

設計は準有効ですが、完全ではありません。

  • 自動インクリメントのunsignedintID列t_usersを使用する方がよいでしょう。(名前の主キーはほとんどの場合悪い考えです。人々は名前を変更します。人々は同じ名前を持っています。国でさえ名前を変更することがあります!ほとんどの場合、数値が最良の選択です!)
  • そうすれt_postsば、そのuserIDを参照できます。現在、結合は急速に進んでいます。
  • 参照整合性を適用することもできます。存在しないユーザーが投稿することはできません。または、ユーザーが削除されると、投稿も削除されます。
  • t_postsID主キー列(良い!)がありますが、varchar(悪い!)です。INTの方が優れています。BIGINTあなたがそれを必要とするならば。

後で投稿に複数のトピックが含まれる可能性があります(stackoverflowの「タグ」)。それらをvarcharフィールドにCSVで入力しないでください。ID、説明、および各投稿を1つ以上のトピックにリンクするリンクテーブル「posts_to_topic」を使用して、新しいテーブル「topics」を作成します。

インデックス

あなたが読む必要があるのはインデックスです。トピック「プログラミング」を持つすべてのコメントをクエリする場合は、通常、列「トピックvarchar(80)」にインデックスがあります。このインデックスは小さいので(別のテーブルと考えてください。インデックス付きの列と主キーが含まれています)、(R)DBMSはこのインデックスを非常にすばやく検索し(ツリー構造)、必要なすべての主キーを取得できます。次に、選択した内容に応じて、DBMSから次の情報が送信されます。

  • すでにインデックスにある列のみが必要な場合は、インデックスからすべてをフェッチできます。
  • 他の列が必要な場合は、実際にt_postsテーブルにアクセスし、インデックスの主キーを使用して行にアクセスするようになりました。

簡素化

私は嘘をついた。最後の段落で、私はそれを実際よりもはるかに単純にしました。クエリを調べて、使用できるインデックスを決定するオプティマイザーがあります。カーディナリティ、テーブルサイズ、使用する可能性のある列に応じて、インデックスをチェックするか、とにかくテーブルをスキャンすることを決定します。テーブルの行の長さが可変の場合、X番目の行のフェッチは、すべての行の長さが同じ(VARCHARなし)の場合よりもはるかに遅くなります。そして、それはすべて、使用する(R)DBMS(または、MySQLではどのストレージエンジンでも)によって異なります。

しかし、最初にインデックスについて、何を、なぜ、そして後でどのように読んでください。その後、例外をより深く研究することができます。

同じデータの複数のテーブル

これは非常に頻繁に行われる初心者の間違いであり、両方の方向に進みます。

  • 「列「TYPE」を追加してすべてをvarcharにすると、すべてを1つのテーブルに入れることができます!」
  • 「データベース、table_1、table_2などに10000個のテーブルを含めることができます!」

インデックスについて読むと、これが技術的に悪い考えである理由がわかりますが、論理的なスケールではあまりエレガントではありません。1つのテーブルは1つのエンティティ(本、ユーザー、投稿、ページ)を表すことを目的としています。これらを分割すると、非常に醜いものになります。クエリ。そして、なぜ彼らがこれをしているのかを誰かに尋ねると、その理由はしばしば「スピードのため」ですが、彼らの意思決定列に追加のインデックスがあれば同じ効果があります。

考えてみてください。ユーザーごとに投稿タイトルを作成する場合は、最もよく使用される10のトピックと、各トピックの投稿数を一覧表示するクエリを記述します。すべてのテーブルに名前を付ける必要があります!

于 2012-05-15T13:14:19.287 に答える
3

最初の 2 つの質問に対する本当の答えは、「はい」と「いいえ」です。「はい」、テーブルはすぐに大きくなります。そして「いいえ」これは一般的にパフォーマンスを損なうことはありません。

テーブルは、結果を見つけるためにスキャンする単一のファイルと考えることができますが、SQL はこれ以上のことを行います。ほとんどすべてのデータベースは、ページ テーブルと呼ばれるものを管理します。これは、次のことを意味します。

  • テーブルが読み取られると、メモリに収まる場合は、移動する必要があるまでそこにとどまります。これにより、テーブルに対するさらなるクエリが大幅に高速化されます。
  • ページ テーブルのロードは、通常、処理とは非同期に行われます。

これらの 2 つのポイントは、それ自体で、ほとんどのプログラミング言語で実装するのが非常に困難です (ただし、不可能ではありません)。さらに、SQL は、1 つのテーブルの処理をさらに高速化できるインデックスとテーブル パーティションを提供します。最後に、SQL のほとんどのバージョンは、ほとんどすべての機能に対して複数のプロセッサ/スレッドをサポートしています。

複数のテーブルからの結果を組み合わせたり、結果を集計したりする場合、データベースでは、結合と集計を行うためのアルゴリズムに何年もの労力がかかります。この状況でうまくやれる可能性は低いです。

また、これらの機能は、データの一貫性の強化、データのバックアップと復元、変更の保証など、リレーショナル データベースの他の多くの機能には影響しません。

あなたのテーブルスキーマに関しては、あなたが始めているようで、問題ありません。一般に、主キーはテーブルにちなんだ名前を付け、整数にすることをお勧めします。最初のテーブルは次のようになります。

CREATE TABLE users (
    UserId int primary key,
    name varchar(80),
    email varchar(80)
); 

そして、2 番目のテーブルの UserId は int として宣言されます。なぜこれが良いのかのヒントとして、ユーザーは時々自分の名前を変更したくなるかもしれません。

于 2012-05-15T13:27:39.370 に答える
1

すべての投稿を新しいテーブルに分割したほうがよいのではないでしょうか?

いいえ。

投稿が異なるテーブルにある場合、すべてのデータを見つけるために、何百、何千もの異なるテーブルにクエリを実行する必要があります。

言うまでもなく、データ (どのテーブルに含まれていても同じサイズになります) に加えて、テーブル自体のオーバーヘッドがあります。

于 2012-05-15T13:14:11.447 に答える