10

私は次の問題に直面しています。私は非常に大きなテーブルを持っています。この表は、以前にプロジェクトに携わった人々からの遺産です。テーブルはMSSQLServerにあります。

テーブルには次のプロパティがあります。

  1. 約300列あります。それらはすべて「テキスト」タイプですが、最終的には他のタイプ(たとえば、整数や日時)を表すものもあります。したがって、このテキスト値を使用する前に、適切なタイプに変換する必要があります。
  2. テーブルには100ミリオム以上の行があります。テーブルのスペースはすぐに1テラバイトに達するでしょう
  3. テーブルにはインデックスがありません
  4. テーブルには、パーティション化のメカニズムが実装されていません。

ご想像のとおり、このテーブルに対して適切なクエリを実行することは不可能です。現在、人々は新しいレコードをテーブルに挿入するだけですが、誰もそれを使用しません。だから私はそれを再構築する必要があります。新しい構造を作成し、新しい構造に古いテーブルのデータを再入力する予定です。もちろん、パーティション分割を実装しますが、実行するのはそれだけではありません。

テーブルの最も重要な機能の1つは、純粋にテキストである(つまり、別のタイプに変換する必要がない)フィールドには、通常、頻繁に繰り返される値があることです。したがって、特定の列の実際の値の種類は、5〜30の異なる値の範囲です。これにより、正規化を行うというアイデアが生まれます。このようなテキスト列ごとに、この列に表示される可能性のあるすべての異なる値のリストを含む追加のテーブルを作成し、次にこの追加のテーブルに(tinyint)主キーを作成します。次に、これらのテキスト値を元のテーブルに保持する代わりに、元のテーブルで適切な外部キーを使用します。次に、この外部キー列にインデックスを付けます。このように処理される列の数は約100です。

それは次の質問を提起します:

  1. この正規化により、100個のフィールドのいくつかに条件を課すクワイアの速度が本当に向上しますか?これらの列を保持するために必要なサイズを忘れた場合、最初のテキスト列をtinyint列に置き換えることでパフォーマンスが向上するかどうか。正規化を行わず、最初のテキスト列にインデックスを付けるだけの場合、パフォーマンスは計画されたtinyint列のインデックスと同じになるかどうか。
  2. 説明した正規化を行う場合、テキスト値を示すビューを作成するには、メインテーブルを約100個の追加テーブルと結合する必要があります。ポジティブな瞬間は、ペア "primary key" ="foreignkey"に対してこれらの結合を実行することです。しかし、それでもかなりの量のテーブルを結合する必要があります。ここに質問があります:このビューに対して行われたクエリのパフォーマンスが、最初の非正規化テーブルに対するクエリのパフォーマンスと比較して悪化しないかどうか。SQL Server Optimizerが、正規化のメリットを享受できる方法でクエリを本当に最適化できるかどうか。

長いテキストでごめんなさい。

コメントありがとうございます!

PS100個のテーブルの結合に関する関連する質問を作成しました。 100個のテーブルを結合する

4

4 に答える 4

7

データに対して実行されるクエリの速度に加えて、データを正規化することには他の利点があります...サイズや保守性など、それだけで正規化を正当化する必要があります...

ただし、クエリの速度も向上する可能性があります。現在、300 個のテキスト列を含む 1 つの行を持つことは膨大であり、行データ ページを格納するための 8,060 バイトの制限をほぼ確実に超えています...代わりにROW_OVERFLOW_DATAまたはLOB_DATAアロケーション ユニットに格納されています。

冗長なテキスト データを外部キーに置き換えるなどの正規化によって各行のサイズを縮小し、TINYINTこの大きなテーブルの主キーに依存しない列を別のテーブルに削除することで、データがオーバーフローしなくなります。 ' また、ページごとにより多くの行を格納できるようになります。

正規化されたデータを取得するために実行することによって追加されるオーバーヘッドに関する限りJOIN...テーブルに適切にインデックスを付ければ、これによりかなりの量のオーバーヘッドが追加されることはありません。ただし、許容できないオーバーヘッドが追加される場合は、必要に応じてデータを選択的に非正規化できます。

于 2013-02-07T19:21:11.713 に答える
5

これが努力する価値があるかどうかは、値の長さに依存します。たとえば、値が州の略語 (2 文字) または国コード (3 文字) である場合、結果のテーブルは既存のテーブルよりもさらに大きくなります。参照テーブルの主キーを含める必要があることに注意してください。これは通常整数で、4 バイトを占めます。

これを行う正当な理由は他にもあります。有効な値のリストを持つ参照テーブルを使用すると、データベースの一貫性が維持されます。参照テーブルは、入力の検証とレポート目的の両方に使用できます。「長い名前」などの追加情報を含めることができます。

また、SQL Server は varchar 列を追加のページにスピルオーバーします。他のタイプはこぼれません。300 列しかありませんが、最終的にレコード データが 1 ページのデータの制限である 8k に近づく可能性があります。

そして、先に進むことにした場合は、コラムで「テーマ」を探すことをお勧めします。グループ化できる列のグループが存在する場合があります。. . 詳細な停止コードと停止カテゴリ、短いビジネス名と完全なビジネス名。データのモデル化の道を進んでいます (良いことです)。ただし、非常に低いレベル (100 の参照テーブルを管理する) で物事を行うことと、合理的なエンティティと関係のセットを特定することには注意が必要です。

于 2013-02-07T19:18:09.477 に答える
2

1) システムは現在、非常に大量のデータに対して完全なテーブル スキャンを実行する必要があり、パフォーマンスの問題が発生しています。このパフォーマンスを改善できる最適化の側面は数多くあります。列を正しいデータ型に変換すると、各レコードのサイズが縮小されてパフォーマンスが大幅に向上するだけでなく、データを正しくすることができます。列に対してクエリを実行している場合、現在、フィールド内のテキストと比較されているテキストを見ています。インデックスを作成するだけでこれは改善される可能性がありますが、ルックアップに変更すると、メモリに保持するのに十分小さいテーブルから ID 値をルックアップし、これを使用して整数値のみをスキャンできるため、プロセスがはるかに高速になります。2) データを第 3 正規形などに正規化すると、次に、データの整合性の名目でパフォーマンスが低下するインスタンスを確認できます。エンジンが最初にデータを射影せずに行を制限する方法を見つけられない場合、これが最も問題になります。ただし、これが発生した場合は、実行計画でこれを特定でき、クエリを修正してこの可能性を減らすことができます。

もう 1 つの注意点は、データベースが適切に構成されていれば、データ量が大幅に削減されるため、メモリにキャッシュできる可能性があることです。これがあれば、パフォーマンスは大幅に向上します。

パフォーマンスを向上させる簡単な方法は、おそらくインデックスを追加することです。ただし、これによりデータベース全体のサイズがさらに大きくなり、重複データの格納の問題やデータの整合性の問題に対処できません。

他にもいくつかの変更を加えることができます。大量のデータが常に必要であるとは限らない場合は、これを関連するテーブルに分離して、必要な場合にのみ参照することができます。他のテーブルへのルックアップに使用されていないフィールドは、これの特定の候補です。実際にデータを識別したときに追加のデータをルックアップするだけのかなり単純な構造を維持しながら、結合をはるかに小さなテーブルにすることができるためです。必要。これは明らかに適切に正規化された構造ではありませんが、(インデックス作成を追加した後に) パフォーマンスを向上させる手っ取り早い方法かもしれません。

于 2013-02-07T19:16:39.757 に答える
1
  1. 正規化されたデータベース構造を頭の中で紙の上に構築する
  2. データベースの構築 (インデックス付き)
  3. そのモノリスを解体します。物事はそれほど悪くはありません。A LOT (I MEAN A LOT) のデータが繰り返されていると思います
  4. データベースにデータを挿入する SQL 挿入ステートメントを作成する
  5. ショットガンで最初にその悪夢を構築した人に行きます。楽しむ。
于 2013-02-07T19:29:46.257 に答える