参加が悪い、または「遅い」のはなぜですか。これを何度も聞いたことがあります。この見積もりを見つけました
問題は、結合が比較的遅いこと、特に非常に大きなデータセットの場合、結合が遅い場合、ウェブサイトが遅いことです。これらの個別の情報をすべてディスクから取り出し、それらをすべてまとめ直すには長い時間がかかります。
特にPKを検索するときは、特に高速だと思っていました。なぜ「遅い」のですか?
参加が悪い、または「遅い」のはなぜですか。これを何度も聞いたことがあります。この見積もりを見つけました
問題は、結合が比較的遅いこと、特に非常に大きなデータセットの場合、結合が遅い場合、ウェブサイトが遅いことです。これらの個別の情報をすべてディスクから取り出し、それらをすべてまとめ直すには長い時間がかかります。
特にPKを検索するときは、特に高速だと思っていました。なぜ「遅い」のですか?
回答:
スケーラビリティとは、ワークユニットごとのリソースの使用を最小限に抑えるために、繰り返される作業を必要最低限のものまで事前計算、分散、または削減することです。適切にスケーリングするために、ボリュームに必要のないことは何もせず、実際に行っていることを確実に行うには、可能な限り効率的に行います。
そのコンテキストでは、もちろん、2つの別個のデータソースを結合することは、少なくともそれらを結合しないことと比較すると、ユーザーが要求した時点でライブで行う必要がある作業であるため、比較的低速です。
ただし、別の方法では2つの別個のデータがまったく存在しないことに注意してください。2つの異なるデータポイントを同じレコードに配置する必要があります。どこかに影響を与えずに2つの異なるデータを結合することはできないため、トレードオフを理解するようにしてください。
良いニュースは、最新のリレーショナルデータベースが結合に優れていることです。良いデータベースがうまく使用されていれば、結合を遅いと考えてはいけません。生の結合を取り、それをはるかに高速にするためのスケーラビリティに適した方法がいくつかあります。
私は限り言うように行くだろう、リレーショナルデータベースがまったく存在した主な理由は、あなたが効率的に参加しないようにすることです*。確かに、構造化されたデータを保存するだけではありません(csvやxmlなどのフラットファイル構成でそれを行うことができます)。私がリストしたいくつかのオプションでは、事前に完全に結合を構築することもできるため、クエリを発行する前に、データを非正規化した場合と同じように、結果が既に行われています(確かに、書き込み操作が遅くなります)。
結合が遅い場合は、データベースを正しく使用していない可能性があります。
非正規化は、これらの他の手法が失敗した後にのみ行う必要があります。そして、「失敗」を本当に判断できる唯一の方法は、意味のあるパフォーマンス目標を設定し、それらの目標を測定することです。測定していない場合、非正規化について考えることも早すぎます。
*つまり、単なるテーブルのコレクションとは異なるエンティティとして存在します。実際のRDBMSのもう1つの理由は、安全な同時アクセスです。
結合は、非正規化によって回避するよりも遅くなる可能性がありますが、適切に使用すると(適切なインデックスを持つ列での結合など)、本質的に遅くなりません。
非正規化は、適切に設計されたデータベーススキーマにパフォーマンスの問題がある場合に検討できる最適化手法の1つです。
まず、リレーショナルデータベースの存在理由(存在理由)は、エンティティ間の関係をモデル化できるようにすることです。結合は、これらの関係をたどるメカニズムです。これらは確かにわずかなコストで提供されますが、結合なしでは、リレーショナルデータベースを用意する理由はありません。
学問の世界では、さまざまな正規形(1次、2次、3次、ボイスコッドなど)のようなものについて学び、さまざまなタイプの鍵(主、外部、代替、一意など)とその方法について学びますこれらを組み合わせてデータベースを設計します。また、SQLの基礎と、構造とデータ(DDLとDML)の両方の操作について学びます。
企業の世界では、多くの学術的構成要素は、私たちが信じていたよりも実質的に実行可能性が低いことが判明しています。完璧な例は、主キーの概念です。学術的には、テーブル内の1つの行を一意に識別する属性(または属性のコレクション)です。したがって、多くの問題領域で、適切な学術的主要キーは3つまたは4つの属性の複合です。ただし、現代の企業世界のほとんどすべての人が、自動生成された連続した整数をテーブルの主キーとして使用しています。どうして?2つの理由。1つ目は、FKをあちこちに移行する場合にモデルがよりクリーンになるためです。2番目の、そしてこの質問に最も密接に関係しているのは、結合を介してデータを取得する方が、単一の整数の方が4つのvarchar列よりも高速で効率的であることです(既に数人が言及しているように)。
ここで、実世界のデータベースの2つの特定のサブタイプについてもう少し詳しく見ていきましょう。最初のタイプはトランザクションデータベースです。これは、最新のサイトを推進する多くの電子商取引またはコンテンツ管理アプリケーションの基盤です。トランザクションDBを使用すると、「トランザクションスループット」に向けて大幅に最適化できます。ほとんどのコマースアプリやコンテンツアプリでは、(特定のテーブルからの)クエリのパフォーマンスと(他のテーブルからの)挿入のパフォーマンスのバランスをとる必要がありますが、各アプリには解決すべき独自のビジネス主導の問題があります。
2番目のタイプの実世界データベースは、レポートデータベースです。これらは、ほぼ独占的にビジネスデータを集約し、意味のあるビジネスレポートを生成するために使用されます。これらは通常、データが生成されるトランザクションデータベースとは形状が異なり、大規模または複雑なデータセットでのバルクデータロード(ETL)の速度とクエリパフォーマンスのために高度に最適化されています。
どちらの場合も、開発者またはDBAは、機能とパフォーマンスの両方の曲線のバランスを慎重に取る必要があり、方程式の両側には、パフォーマンスを強化するための多くのトリックがあります。Oracleでは、「説明計画」と呼ばれる処理を実行できるので、クエリがどのように解析および実行されるかを具体的に確認できます。DBのインデックスの適切な使用を最大化しようとしています。本当に厄介なのは、クエリのwhere句に関数を配置することです。これを行うときはいつでも、Oracleがその特定の列でインデックスを使用しないことを保証し、Explainプランでテーブルの完全または部分的なスキャンが行われる可能性があります。これは、クエリがどのように記述されて低速になる特定の例にすぎず、結合とは何の関係もありません。
また、テーブルスキャンについて説明している間、テーブルのサイズに比例してクエリ速度に明らかに影響します。100行のフルテーブルスキャンは目立ちません。1億行のテーブルで同じクエリを実行すると、来週に戻って戻ってくる必要があります。
正規化について少し話しましょう。これは、過度にストレスがかかる可能性のある、もう1つの大きな肯定的な学術トピックです。私たちが正規化について話すとき、ほとんどの場合、それは実際にそれを独自のテーブルに入れてFKを移行することによって重複データを排除することを意味します。人々は通常、2NFと3NFによって記述される依存関係の全体をスキップします。さらに、極端な場合でも、非常に正規化されているため、巨大で完全な獣をコード化する完璧なBCNFデータベースを作成することは確かに可能です。
では、どこでバランスを取るのでしょうか?単一のベストアンサーはありません。より良い答えはすべて、構造の保守の容易さ、データの保守の容易さ、およびコードの作成/保守の容易さの間の妥協である傾向があります。一般に、データの重複が少ないほど良いです。
では、なぜ結合が遅くなるのですか?時々それは悪い関係設計です。時々それは効果的な索引付けではありません。時々それはデータ量の問題です。ひどく書かれたクエリである場合もあります。
このように長々とした答えで申し訳ありませんでしたが、私は4箇条書きの応答をただガタガタと鳴らすのではなく、コメントの周りにもっと重要なコンテキストを提供することを強いられました。
テラバイトサイズのデータベースを使用している人々は、パフォーマンスの面で機能させることができれば、結合を使用できます。
デノマライズしない理由はたくさんあります。まず、選択クエリの速度だけがデータベースの主な関心事ではありません。データの整合性が最初の関心事です。非正規化する場合は、親データが変更されたときにデータを非正規化しておくための手法を導入する必要があります。したがって、client_Idでクライアントテーブルに参加するのではなく、すべてのテーブルにクライアント名を格納するとします。ここで、クライアントの名前が変更された場合(クライアントの名前の一部が時間とともに変更される可能性は100%です)、その変更を反映するようにすべての子レコードを更新する必要があります。カスケード更新でこれを実行し、100万の子レコードがある場合、それがどのくらいの速さであり、ロック問題が発生し、それが発生している間、作業の遅延を被るユーザーは何人いると思いますか?さらに、非正規化するほとんどの人は
非正規化は複雑なプロセスであり、正しく実行するには、データベースのパフォーマンスと整合性を完全に理解する必要があります。スタッフにそのような専門知識がない限り、非正規化を試みないでください。
いくつかのことを行うと、結合は非常に高速になります。最初にサゴゲートキーを使用します。int結合は、最速の結合です。次に、常に外部キーにインデックスを付けます。派生テーブルまたは結合条件を使用して、フィルタリングする小さなデータセットを作成します。大規模で非常に複雑なデータベースがある場合は、巨大なデータベースの分割と管理の経験を持つ専門のデータベース担当者を雇います。結合を削除せずにパフォーマンスを向上させるためのテクニックはたくさんあります。
クエリ機能だけが必要な場合は、そうです。非正規化が可能で、ユーザーデータエントリではなくETLツール(速度を最適化したもの)を介して入力されるデータウェアハウスを設計できます。
両側のレコードの大部分をスキャンする必要がある場合、結合が遅くなる可能性があります。
このような:
SELECT SUM(transaction)
FROM customers
JOIN accounts
ON account_customer = customer_id
でインデックスが定義されている場合でもaccount_customer
、後者のすべてのレコードをスキャンする必要があります。
クエリリストの場合、適切なオプティマイザはインデックスアクセスパスを考慮せずHASH JOIN
、MERGE JOIN
代わりにa またはa を実行します。
次のようなクエリの場合は注意してください。
SELECT SUM(transaction)
FROM customers
JOIN accounts
ON account_customer = customer_id
WHERE customer_last_name = 'Stellphlug'
結合はおそらく高速になります。最初に、customer_last_name
すべてのStellphlug(もちろん、それほど多くはありません)をフィルターするためにインデックスオンが使用されます。次に、account_customer
Stellphlugごとにインデックススキャンが発行され、トランザクションを見つけます。
これらはaccounts
およびcustomers
で数十億のレコードになる可能性があるという事実にもかかわらず、実際にスキャンする必要があるのはごくわずかです。
accounts(account_customer)
ほとんどのRDBMSでインデックスが定義されている場合、そのインデックスを使用して、customers
スキャンする必要があるデータベースの行を正確に特定します。
HASH JOIN
方がはるかに高速なのでMySQL
、を除くすべての主要なデータベースを除いて使用されます。ただし、customers
ネストされたループで先頭に立つだけです(サイズが小さいため)
Joins are fast.
結合は、適切に正規化されたデータベーススキーマを使用する標準的な方法と見なされます。結合を使用すると、データの異なるグループを有意義な方法で結合できます。参加を恐れないでください。
注意点は、インデックスの正規化、結合、および適切な使用を理解する必要があることです。
すべての開発プロジェクトで失敗する最大の原因は期限を満たしているため、時期尚早の最適化に注意してください。プロジェクトを完了し、トレードオフを理解したら、正当化できればルールを破ることができます。
データセットのサイズが大きくなると、結合のパフォーマンスが非線形的に低下するのは事実です。したがって、単一のテーブルクエリほどうまく拡張できませんが、拡張は可能です。
鳥が翼を持たずに速く飛ぶのは真実であるということも事実です。
結合では、データを「結合」するためにより多くのファイルとインデックスを調べる必要があるため、追加の処理が必要です。ただし、「非常に大きなデータセット」はすべて相対的です。largeの定義は?結合の場合、それは全体的なデータセットではなく、大きな結果セットへの参照だと思います。
ほとんどのデータベースは、プライマリテーブルから5つのレコードを選択し、各レコードの関連テーブルから5つのレコードを結合するクエリを非常に迅速に処理できます(正しいインデックスが設定されている場合)。これらのテーブルには、それぞれ数億、または数十億のレコードを含めることができます。
結果セットが成長し始めると、状況は遅くなります。同じ例を使用して、プライマリテーブルの結果が100Kレコードの場合、500Kの「結合された」レコードが見つかる必要があります。追加の遅延を伴い、データベースからデータをプルするだけです。
結合は避けないでください。データセットが「非常に大きく」なると、最適化/非正規化が必要になる場合があることを知っておいてください。
また、引用した記事から:
何十億ものレコード、ペタバイトのデータ、何千もの同時ユーザー、1日に何百万ものクエリが実行される多くのメガスケールのWebサイトは、シャーディングスキームを使用しており、データ層を構築するための最適な戦略として非正規化を主張しているウェブサイトもあります。
そして
そして、あなたが本当に大規模なウェブサイトでなければ、おそらくこのレベルの複雑さについて心配する必要はないでしょう。
そして
データベースにこの作業をすべて行わせるよりもエラーが発生しやすくなりますが、最上位のデータベースでも処理できる範囲を超えて拡張することができます。
この記事では、Ebayのようなメガサイトについて説明しています。その使用レベルでは、単純なバニラリレーショナルデータベース管理以外のものを検討する必要があるでしょう。しかし、「通常の」ビジネスコース(数千のユーザーと数百万のレコードを持つアプリケーション)では、これらのより高価でエラーが発生しやすいアプローチは過剰です。
適切なインデックスと適切に作成されたクエリを含む適切に設計されたテーブルは常に遅くなるとは限りません。あなたが聞いたことがあるところ:
参加が悪い、または「遅い」のはなぜですか
彼らが何について話しているのか分かりません!!! ほとんどの結合は非常に高速になります。一度に多くの行を結合する必要がある場合は、非正規化されたテーブルと比較してヒットする可能性がありますが、それは適切に設計されたテーブルに戻ります。重いレポートシステムでは、レポート用に非正規化テーブルのデータを分割するか、データウェアハウスを作成します。トランザクションの多いシステムでは、テーブルを正規化します。
生成される一時データの量は、結合に基づいて膨大になる可能性があります。
たとえば、ここで使用している1つのデータベースには、すべてのフィールドがオプションである一般的な検索機能がありました。検索ルーチンは、検索が始まる前にすべてのテーブルで結合を行いました。これは最初はうまくいきました。しかし、メインテーブルには1,000万行以上あるので、それほど多くはありません。検索には30分以上かかります。
検索ストアドプロシージャを最適化する必要がありました。
最初に行ったのは、メインテーブルのフィールドのいずれかが検索されている場合、それらのフィールドのみで一時テーブルを選択しました。その後、残りの検索を行う前に、すべてのテーブルをその一時テーブルに結合しました。メインテーブルフィールドの1つが10秒未満である検索。
メインテーブルのフィールドが検索されない場合は、他のテーブルに対しても同様の最適化を行います。私が終わったとき、検索に30秒以上かかることはなく、ほとんどの場合10以下です。
SQLサーバーのCPU使用率もWAY DOWNになりました。