2

1,000 万行近くの個人情報を格納するテーブルがあります。

現在、State は person テーブルの char(2) フィールドです。これにより、予想どおり、大量のデータの重複が発生します。State データを独自のテーブルに正規化し、person テーブルで FK を作成すると、クエリ時間が短縮されますか?

前:

SELECT Name, City, State FROM Person WHERE State = 'WI'

後:

SELECT p.Name, p.City, s.Name as State
FROM Person p
    INNER JOIN State s ON p.State == s.Id
WHERE s.Name = 'WI'

これによりパフォーマンスが向上するように思えますが、クエリの最適化に関しては専門家とは言えません。

4

6 に答える 6

2

正規化によりパフォーマンスが低下する可能性がありますが、このような場合にパフォーマンスが向上することはめったにありません。これは、サーバーがディスク上の 1 つだけではなく 2 つの場所を参照する必要があるためです。

正規化には 2 つの目的があります。

  1. ディスクに保存されるデータの量を減らす
  2. 1 か所でデータを更新できるようにする

クエリは、これらの利点のいずれからも恩恵を受けません。

  1. char(2) と int (外部キー) の間に大きな違いはありません。
  2. 州の 2 桁のコードは変更されないため、更新する必要はありません。
于 2012-10-05T13:10:29.867 に答える
1

2文字について話しているだけの場合は、おそらくそれを新しいテーブルに分割するのにあまり使用されません。

(ただし、許可されている値の特定のドメインがあることを考慮してください-誰かがVXまたはその他の許可されていない値を入力した場合はどうなりますか?非正規化されたときに適切または効率的に制約する方法はありません)

米国の郵便の略語(2文字)や州の氏名、その他の情報など、他の情報について話している場合は、絶対にそうです。分割してください。

実際問題として、適切な正規化の側で常にエラー(imo)を実行する必要があります。長い議論の後は、非正規化を検討する必要があります。

于 2012-10-05T13:15:11.600 に答える
1

TINYINT のように状態テーブルに非常に狭いキーを作成すると、パフォーマンスが向上しますが、保証はされません。ただし、テストする価値は十分にあります。

各テーブルの複製を作成し、適切にインデックスを作成してから、アナライザーを使用して両方に対して同時にクエリを実行することを検討してください。

速度が 1% 向上する可能性があります。

それでも、正規化が悪い考えであることはめったにありません...

于 2012-10-05T13:15:44.373 に答える
0

保存するスペースがあまりありません。
状態は50しかないため、状態テーブルの主キーにバイト(tinyint)を使用できます。
Char(2)は2バイトです。
したがって、personテーブルの1行あたり1バイトしか保存しません。

データをコンパクトにする利点は、ディスク容量とメモリが少ないことです。
固定量のメモリの場合、データが小さいと、メモリ内のデータの可能性が高くなります。

結合のオーバーヘッドに見合う1バイトのサイズの違いはないと思います。

しかし、それが良い習慣であるという理由だけで、私は正規化します。
なぜ誰かをJZの状態にするのですか?

3番目の正規形に失敗
する3NFを達成
する繰り返しグループがある場合は、グループを独自の関係に分離します。

状態テーブルのPKとしてchar(2)を使用できるため、char(2)とchar(2)が直接一致します。
値が50の状態に制限されているため、これは3番目の正規形を満たします。
その場合、実際の値はプライマリテーブルにあるため、選択に参加する必要はありません。
挿入または更新時にFK関係が適用されるため、有効な状態である必要があります。

状態全体をレポートする場合は、フルネームの列を状態テーブルに追加できます。

于 2012-10-05T13:22:00.297 に答える
0

まあ..あなたのクエリでは、最適ではないことをしています。

SELECT p.Name, p.City, s.Name as State
FROM   Person p
       INNER JOIN State s ON p.State == s.Id
WHERE s.Name = 'WI'

すべての状態のレコードを持つすべての人の詳細を取得し、その後、状態を「WI」でフィルタリングしています..

これを試してみると、状態が少なくなります!

SELECT p.Name, p.City, s.Name as State
FROM   Person p
       INNER JOIN State s 
         ON  p.State == s.Id
         and s.Name = 'WI'

なんで?すべての状態列ではなく、名前が WI である状態列のみを取得するためです。

その後..インデックスに適合する場合は、name = 'WI' の状態でフィルター処理されたインデックスを作成します。

それはいくつかを助けるだろう..

于 2012-10-06T18:59:34.677 に答える
-2

文字列インデックスでの検索は、(理論上) int インデックスでの検索よりもはるかに遅くなります。つまり、はい。データを正規化すると、データが高速になります。実際には、違いが最小限であることがよくあります。YMMV。状態 ID を事前にキャッシュするか、個別に選択する必要がある場合があります。

SELECT p.Name, p.City, s.Name as State
FROM Person p
INNER JOIN State s ON p.State == s.Id
WHERE s.Id = (select id from State where State.Name = 'WI');

クエリの場合と同様に、テストして最適化することをお勧めします。

于 2012-10-05T13:17:14.807 に答える