パフォーマンスを向上させるために非正規化しますか?説得力があるように聞こえますが、水を保持していません。
テッドコッド博士と一緒にリレーショナルデータモデルの最初の支持者であったクリスデイトは、正規化に対する誤った情報に基づく議論で忍耐力を使い果たし、科学的方法を使用してそれらを体系的に破壊しました。彼は大規模なデータベースを取得し、これらの主張をテストしました。
彼は1988-1991年のRelationalDatabaseWritingsでそれを書いたと思いますが、この本は後にデータベース理論と設計の決定的なテキストであるデータベースシステム入門の第6版に巻き込まれ、私が書いている第8版で、今後も続く可能性があります。今後数十年にわたって印刷されます。クリス・デイトは、私たちのほとんどがまだ裸足で走り回っていたとき、この分野の専門家でした。
彼はそれを見つけました:
- それらのいくつかは特別な場合に当てはまります
- それらのすべては、一般的な使用のために報われることができません
- それらのすべては、他の特別な場合には著しく悪化します
それはすべて、ワーキングセットのサイズを軽減することに戻ります。正しく選択されたキーと正しく設定されたインデックスを含む結合は、行が実体化される前に結果を大幅にプルーニングできるため、安価であり、高価ではありません。
結果の具体化には、演習の最も費用のかかる側面であるバルクディスク読み取りが含まれます。対照的に、結合を実行するには、論理的にはキーのみを取得する必要があります。実際には、キー値もフェッチされません。キーハッシュ値は結合の比較に使用され、複数列の結合のコストを軽減し、文字列の比較を伴う結合のコストを大幅に削減します。キャッシュにはるかに収まるだけでなく、実行するディスク読み取りがはるかに少なくなります。
さらに、優れたオプティマイザーは、最も制限の厳しい条件を選択し、結合を実行する前にそれを適用します。これにより、カーディナリティの高いインデックスでの結合の高い選択性を非常に効果的に活用できます。
確かに、このタイプの最適化は非正規化データベースにも適用できますが、スキーマを非正規化したい種類の人々は、通常、インデックスを設定するときにカーディナリティについて考えません。
テーブルスキャン(結合を生成する過程でテーブル内のすべての行を調べる)は実際にはまれであることを理解することが重要です。クエリオプティマイザーは、次の1つ以上が成立する場合にのみテーブルスキャンを選択します。
- リレーションの行数は200未満です(この場合、スキャンの方が安くなります)
- 結合列に適切なインデックスがありません(これらの列で結合することに意味がある場合、なぜそれらはインデックス付けされないのですか?修正してください)
- 列を比較する前に型強制が必要です(WTF ?!修正するか、家に帰る)ADO.NETの問題に関するエンドノートを参照してください
- 比較の引数の1つは、式(インデックスなし)です。
操作を実行すると、実行しないよりもコストがかかります。ただし、間違った操作を実行し、無意味なディスクI / Oに強制されてから、本当に必要な結合を実行する前にドロスを破棄すると、はるかにコストがかかります。「間違った」操作が事前に計算され、インデックスが適切に適用されている場合でも、重大なペナルティが残ります。結合を事前計算するための非正規化は、更新の異常が伴うにもかかわらず、特定の結合へのコミットメントです。別の参加が必要な場合、そのコミットメントはあなたに大きなコストをかけることになります。
変化する世界であることを誰かに思い出させたいのであれば、より大きなハードウェア上のより大きなデータセットは、Dateの調査結果の広がりを誇張していることに気付くと思います。
課金システムや迷惑メールジェネレーター(恥ずかしい)に取り組んでいて、非正規化の方が速いという事実を知っていることを私に伝えるために憤慨してキーボードに手を設定しているすべての人にとって、申し訳ありませんが、あなたは特別なものの1つに住んでいますケース-具体的には、すべてのデータを順番に処理する場合。それは一般的なケースではなく、あなたはあなたの戦略において正当化されます。
あなたはそれを誤って一般化することは正当化されません。データウェアハウジングシナリオでの非正規化の適切な使用の詳細については、注記セクションの最後を参照してください。
返信したいのですが
結合は、リップグロスを備えた単なるデカルト積です。
なんてたくさんのbollocks。制限はできるだけ早く適用され、最も制限が最初に適用されます。あなたは理論を読みましたが、それを理解していません。結合は、クエリオプティマイザーによってのみ「述語が適用されるデカルト積」として扱われます。これは、シンボリック分解を容易にするシンボリック表現(実際には正規化)であるため、オプティマイザーは同等の変換をすべて生成し、コストと選択性でランク付けして、最適なクエリプランを選択できます。
オプティマイザーにデカルト積を生成させる唯一の方法は、述語の提供に失敗することです。SELECT * FROM A,B
ノート
David Aldridgeは、いくつかの重要な追加情報を提供しています。
実際、インデックスとテーブルスキャン以外にもさまざまな戦略があり、最新のオプティマイザーは実行プランを作成する前にそれらすべてにコストをかけます。
実用的なアドバイス:外部キーとして使用できる場合は、インデックスを作成して、オプティマイザーがインデックス戦略を利用できるようにします。
以前は、MSSQLオプティマイザーよりも賢いものでした。それは2つのバージョン前に変更されました。今では一般的に教えてくれます。それは、非常に現実的な意味で、エキスパートシステムであり、ルールベースのシステムが効果的であるほど十分に閉じられたドメイン内の多くの非常に賢い人々のすべての知恵を成文化しています。
「Bollocks」は無知だったかもしれません。私は傲慢ではないように頼まれ、数学は嘘をつかないことを思い出させます。これは真実ですが、数学モデルのすべての意味が必ずしも文字通りに解釈されるべきではありません。負の数の平方根は、それらの不条理を注意深く調べることを避け(そこでしゃれ)、方程式を解釈しようとする前にそれらをすべてキャンセルすることを気にしない場合に非常に便利です。
私がとても野蛮に答えた理由は、言葉通りの声明が次のように言っているからです
結合はデカルト積です...
これは意図されたものではないかもしれませんが、書かれたものであり、断固として真実ではありません。デカルト積は関係です。結合は関数です。より具体的には、結合は関係値関数です。空の述語を使用すると、デカルト積が生成されます。これをチェックすることは、データベースクエリエンジンの1つの正しさチェックですが、教室の外では実用的な価値がないため、実際には制約のない結合を記述しません。
読者がモデルとモデル化されたものを混同するという古代の罠に陥ってほしくないので、私はこれを呼びました。モデルは近似値であり、操作を便利にするために意図的に簡略化されています。
テーブルスキャン結合戦略の選択のカットオフは、データベースエンジンによって異なる場合があります。これは、ツリーノードのフィルファクター、キー値のサイズ、アルゴリズムの微妙さなど、多くの実装上の決定の影響を受けますが、大まかに言えば、高性能インデックスの実行時間はk log n + cです。C項は、主にセットアップ時間で構成される固定オーバーヘッドであり、曲線の形状は、 nが数百になるまで(線形検索と比較して)見返りが得られないことを意味します。
時々非正規化は良い考えです
非正規化は、特定の参加戦略への取り組みです。前述のように、これは他の結合戦略を妨害します。ただし、ディスクスペースのバケット、予測可能なアクセスパターン、およびその大部分またはすべてを処理する傾向がある場合は、結合を事前に計算することは非常に価値があります。
また、操作で通常使用されるアクセスパスを把握し、それらのアクセスパスのすべての結合を事前計算することもできます。これはデータウェアハウスの背後にある前提です。少なくとも、流行語に準拠するためだけでなく、自分がやっていることをなぜやっているのかを知っている人々によって構築されている場合です。
適切に設計されたデータウェアハウスは、正規化されたトランザクション処理システムからの一括変換によって定期的に生成されます。オペレーションとレポートデータベースのこの分離は、OLTPとOLAPの間の衝突を排除するという非常に望ましい効果をもたらします(オンライントランザクション処理、つまりデータ入力、およびオンライン分析処理、つまりレポート)。
ここで重要な点は、定期的な更新とは別に、データウェアハウスは読み取り専用であるということです。これにより、更新の異常の問題が浮き彫りになります。
OLTPデータベース(データ入力が行われるデータベース)の非正規化を間違えないでください。請求の実行は高速になる可能性がありますが、そうすると更新の異常が発生します。リーダーズダイジェストにあなたに物を送るのをやめさせようとしたことがありますか?
最近のディスク容量は安いので、ノックアウトしてください。しかし、非正規化はデータウェアハウスの話の一部にすぎません。事前に計算されたロールアップ値、つまり月間合計などから、はるかに大きなパフォーマンスの向上が得られます。それは常にワーキングセットを減らすことです。
タイプの不一致に関するADO.NETの問題
varchar型のインデックス付き列を含むSQLServerテーブルがあり、AddWithValueを使用して、この列のクエリを制約するパラメーターを渡すとします。C#文字列はUnicodeであるため、推測されるパラメータタイプはNVARCHARになりますが、これはVARCHARとは一致しません。
VARCHARからNVARCHARへの変換は拡大するため、暗黙的に発生しますが、インデックス作成に別れを告げ、その理由を理解してください。
「ディスクヒットを数える」(リック・ジェームス)
すべてがRAMにキャッシュされている場合は、JOINs
かなり安価です。つまり、正規化にはパフォーマンスの低下はあまりありません。
「正規化された」スキーマによってJOINs
ディスクが頻繁にヒットするが、同等の「非正規化された」スキーマがディスクにヒットする必要がない場合、非正規化はパフォーマンスの競争に勝ちます。
元の作成者からのコメント:最新のデータベースエンジンは、アクセスシーケンスを整理して、結合操作中のキャッシュミスを最小限に抑えるのに非常に優れています。上記は真実ですが、結合が大規模なデータでは必然的に問題のあるコストがかかることを意味すると誤解される可能性があります。これは、経験の浅い開発者の意思決定の質を低下させることにつながります。