8

私の2つの質問は次のとおりです。

  • クラスタ化インデックスを使用して、大きなテーブルへの一括挿入を高速化できますか?
  • IDENTITY列がクラスター化インデックスではなくなった場合でも、外部キー関係を効率的に使用できますか?

詳細に説明すると、会社のデータを含む非常に大きな(100〜1000百万行の)テーブルがいくつかあるデータベースがあります。通常、このようなテーブルには20〜40の企業に関するデータがあり、それぞれが「CompanyIdentifier」(INT)でマークされた独自の「チャンク」です。また、すべての企業には約20の部門があり、それぞれに「DepartmentIdentifier」(INT)でマークされた独自の「サブチャンク」があります。

「チャンク」または「サブチャンク」全体がテーブルに追加またはテーブルから削除されることがよくあります。私が最初に考えたのは、これらのチャンクでテーブルパーティショニングを使用することでしたが、SQL Server 2008 Standard Editionを使用しているため、その資格がありません。それでも、私が持っているほとんどのクエリは、テーブル全体ではなく、「チャンク」または「サブチャンク」で実行されます。

私はこれらのテーブルを次の機能のために最適化するために取り組んできました:

  1. サブチャンクで実行されるクエリ
  2. テーブル全体で実行される「ベンチマーク」クエリ
  3. データの大きなチャンクの挿入/削除。

1)と2)については、私は多くの問題に遭遇していません。キーフィールド(有用な場合はCompanyIdentifierとDepartmentIdentifierも含む)にいくつかのインデックスを作成しましたが、クエリは正常に実行されています。

しかし、3)私は良い解決策を見つけるのに苦労しました。私の最初の戦略は、常にインデックスを無効にし、大きなチャンクを一括挿入し、インデックスを再構築することでした。これは最初は非常に高速でしたが、データベースに多くの企業が存在するようになったため、毎回インデックスを再構築するのに非常に長い時間がかかります。

現時点では、これがより高速になっているように見えるため、私の戦略は挿入中にインデックスをオンのままにすることに変更されました。しかし、挿入速度をさらに最適化したいと思います。

CompanyIdentifier + DepartmentIdentifierで定義されたクラスター化インデックスを追加することにより、テーブルへの新しい「チャンク」のロードが高速になることに気付いたようです。IDENTITY列にクラスター化インデックスを追加するためにこの戦略を放棄する前は、クラスター化インデックスは他のすべてのインデックスに含まれているため、クラスター化インデックスはできるだけ小さくする必要があると指摘されていました。しかし今、私はこの古い戦略を復活させてインサートをスピードアップすることを考えています。私の質問ですが、これは賢明なことでしょうか、それとも他の分野でパフォーマンスの低下に見舞われるのでしょうか?そして、これは本当に私の挿入をスピードアップしますか、それともそれは私の想像力ですか?

また、私の場合、IDENTITY列が本当に必要かどうかもわかりません。他のテーブルとの外部キー関係を確立できるようにしたいのですが、CompanyIdentifier + DepartmentIdentifier + [uniquifier]スキームのようなものを使用することもできますか?または、テーブル全体の断片化されたIDENTITY番号である必要がありますか?

提案や説明をありがとうございました。

4

6 に答える 6

4

さて、私はそれをテストしました、そして2つの「チャンク定義」列にクラスター化インデックスを置くことは私のテーブルのパフォーマンスを向上させます。

チャンクの挿入は、クラスター化されたIDENTITYキーがある状況と比較して比較的高速であり、クラスター化されたインデックスがない場合とほぼ同じ速度です。チャンクの削除は、クラスター化されたインデックスがある場合とない場合よりも高速です。

削除または挿入したいすべてのレコードがハードディスクの特定の部分にすべて一緒にあることが保証されているという事実は、テーブルを高速化すると思います-それは私には論理的に思えます。


更新:この設計で1年の経験を積んだ後、このアプローチを機能させるには、すべてのインデックスの定期的な再構築をスケジュールする必要があると言えます(週に1回実行します)。そうしないと、インデックスがすぐに断片化され、パフォーマンスが低下します。それでも、パーティション化されたテーブルを備えた新しいデータベース設計への移行の過程にあります。これは、Enterprise Serverのライセンスコストを除いて、基本的にすべての点で優れていますが、すでに忘れています。少なくとも私は持っています。

于 2010-09-29T21:34:40.303 に答える
1

クラスタ化インデックスは、物理インデックス、物理データ構造、行の順序です。クラスタ化されたインデックスの中央に挿入すると、データは現在のデータの中央に物理的に挿入されます。この場合、深刻なパフォーマンスの問題を想像します。私はこれを理論からしか知りません。なぜなら、これを実際に行うと、私の理論的知識によれば間違いになるからです。

したがって、順序を維持しながら、常に物理的に最後に挿入されるフィールドでのみ、クラスター化インデックスを使用します(使用をお勧めします)。

クラスター化されたインデックスは、挿入の瞬間などをマークする日時フィールドに配置できます。これは、物理的には行を追加した後に順序付けられるためです。IDも優れたクラスター化インデックスですが、クエリに常に関連するとは限りません。

あなたのソリューションでは、[uniquifier]フィールドを配置しますが、それを実行するIDを配置できるのに、なぜこれを行うのでしょうか。これは、一意で、物理的に順序付けられ、小さく(他のテーブルの外部キーの場合はインデックスが小さいことを意味します)、場合によっては高速になります。

これを試してみませんか、実験してみてください。私はここでも同様の状況にあり、40億行あり、常に挿入が増えており(1秒あたり最大100)、テーブルには主キーとクラスター化インデックスがないため、このトピックの提案は私にとっても非常に興味深いものです。

于 2010-09-17T08:43:10.743 に答える
1

クラスタ化インデックスを使用して、大きなテーブルへの一括挿入を高速化できますか?

一度もない!そのテーブルに配置して物理的に順序付けする必要がある別の100万行を想像してみてください。これは、長期的にはパフォーマンスの大幅な低下です。

IDENTITY列がクラスター化インデックスではなくなった場合でも、外部キー関係を効率的に使用できますか?

絶対。ちなみに、クラスター化されたインデックスは特効薬ではなく、通常のインデックスよりも遅い場合があります。

于 2010-09-17T09:02:27.767 に答える
1

System.Data.SqlClient.SqlBulkCopyAPIを見てください。データベースに大量の行を書き込み、データベースから書き込みを行うという要件を考えると、それが必要な場合がありますか?

一括コピーは、1回の操作でデータをテーブルにストリーミングし、インデックスチェックを1回実行します。私はこれを使用してデータベーステーブルに500,000行をコピーし、アプリケーションがAPIを使用するように構造化できると仮定すると、そのパフォーマンスは私が試した他のどの手法よりも桁違いに優れていますか?

于 2010-09-29T21:39:51.603 に答える
0

(あなたがすでに回答を選択し、自分自身にポイントを与えているとすると、これは無料のサービス、慈善行為として提供されます!)

少しの知識は危険なことです。考慮すべき多くの問題があります。そしてそれらは一緒に考慮されなければなりません。いずれか1つの問題を取り上げてそれを個別に調査することは、データベースの管理を行うための非常に断片化された方法です。新しい真実を見つけ、以前考えていたすべてのことを変えることになります。起動する前に、コンテキストについてこの▶質問/回答◀をお読みください。

最近では、キーボードとモデムを持っている人なら誰でも「論文」を公開できることを忘れないでください。それらのいくつかはMSのために働き、最新の「強化」を伝道します。他の人は、1つのコンテキストで、一度も使用したことがない、または一度だけ使用した機能の熱烈なレポートを公開していますが、すべてのコンテキストで機能することを公開しています。(スペンスの答えを見てください:彼は熱狂的で「売られています」が、精査の下で、声明は誤りです。彼は悪い人ではなく、MSの世界の大衆と彼らがどのように運営するか、彼らがどのように出版するかについて典型的です。)

  • 注:MicroSoftiesという用語は、資格のない人なら誰でもデータベースを管理できるというゲーティアンの概念を信じている人を表すために使用します。そしてそのMSはすべてを修正します。それは、魔法への信念と物理法則の停止のために、侮辱としてではなく、愛情として意図されています。

クラスター化されたインデックス

MS全体よりも多くの頭脳を持つ実際のエンジニア(Sybase、MSがコードを取得する前)によって、リレーショナルデータベース用に設計されました。リレーショナルデータベースには、IoTキーではなく、リレーショナルキーがありIdます。これらは複数列のキーであり、データを自動的に分散するため、挿入の負荷が大きくなります。さまざまな会社の請求書を常に挿入します(ただし、説明した「チャンク」の場合はそうではありません)。

  • 優れたリレーショナルキーがある場合、CIは範囲クエリ((1)と(2))、およびNCIにはないその他の利点を提供します。

  • 列から始めてId、データをモデル化して正規化する前に、モデル化と正規化のプロセスを大幅に妨げます。

  • IoTデータベースがある場合は、そうIdでないよりも多くのインデックスがあります。多くのMSデータベースの内容は「リレーショナル」ではなく、通常は正規化されていないファイリングシステムであり、正規化されたデータベースよりもはるかに多くのインデックスがあります。したがって、これらの妊娠中絶を少しスピードアップしようとする大きな推進力、多くのMS「強化」があります。症状を修正しますが、症状の原因となった問題の近くには行かないでください。

  • SQL 2005と2008年に、MSはCIを台無しにしました。その結果、CIはいくつかの点で改善されましたが、他の点では悪化しています。CIの普遍性は失われました。

  • NCIがCIを伝送するのは正しくありません(CIは基本的な単一のストレージ構造です。NCIはセカンダリであり、CIに依存します。そのため、CIを再作成すると、すべてのNCIが自動的に再作成されます)。NCIは、リーフレベルでCIキーを伝送します。

  • Microsoftには問題があり、メジャーリリースで変更されます(ただし、削除されません)。

    • また、MSではこれが効率的に行われないため、NCIインデックスサイズが大きくなります。エンタープライズDBMSでは、これが効率的に行われる場合、これは考慮事項ではありません。

    • したがって、MSの世界では、CIキーをできるだけ短くする必要があるというのは半分しか真実ではありません。考慮事項がNCIのサイズであることを理解し、その費用を負担する意思がある場合は、慎重に構築されたCIにより非常に高速なテーブルに戻るので、それが最良のオプションです。

    • CIをIoTカラムにするという一般的なアドバイスはId、完全に間違っています。CIキーの最悪の候補は、単調に増加する値(IDENTITY、DATETIMEなど)です。なぜ ?すべての同時挿入が現在の挿入位置(インデックスの最後のページ)に対して競合することが保証されているためです。

    • パーティショニング(エンタープライズベンダーから10年後にMSが提供したもの)の本当の目的は、この負荷を分散することです。確かに、パーティションを割り当てる方法を提供する必要があります。推測では、リレーショナルキーにすぎません。しかし、そもそも、IdIoTキーは32または64のパーティションに分散され、より優れた同時実行性を提供します。

  • CIは一意である必要があります。リレーショナルデータベースは一意のキーを要求するため、これは簡単です。

    • しかし、非リレーショナルコンテンツをデータベースに注ぎ込んだアマチュアにとって、このルールを知らないが、CIがデータを拡散することを知っている場合(少しの知識は危険なことです)、彼らIdはNCIにIoTキーを保持します(良い)しかし、それらはほとんど、しかし完全ではない一意のキーでCIを作成します。致命的。CIは一意である必要があります。つまり、設計上の要求です。重複する(ここではCIキーについて話していることを思い出してください)行はページ外で、オーバーフローページにあり、(その後)最後のページにあります。そして、ページチェーンをひどく断片化する方法を構成します。

    • この点は他の場所で疑問視されているので、更新してください。 私はすでにMSが問題を修正せずにメソッドを変更し続けると述べました。

      • MS Onlineのマニュアルには、(技術的な図ではなく)きれいな写真が掲載されており、2008年に、オーバーフローページが愛らしい「Uniqueifier」に置き換えられた(別のページに置き換えられた)と書かれています。

      • それはMicroSoftiesを完全に満足させます。非一意のCIは問題ではありません。それは魔法によって処理されます。名探偵コナン

      • しかし、ステートメントには論理や完全性はなく、資格のある人々は明白な質問をします:この「ユニーク」はどこにありますか?すべての行、または「一意化」が必要な行のみ。DBBC PAGEは、すべての行にあることを示しています。そのため、MSは、一意でない行のみのいくつかのオーバーフローページではなく、すべての行に4バイトのシークレット列(オーバーヘッドの処理を含む)を追加しました。それが工学のMSの考えです。

      • 更新を終了

    • とにかく、要点は残っています。非一意のCIにはかなりのオーバーヘッドがあり(現在は以前よりも多い)、回避する必要があります。一意性を強制するために、1バイトまたは2バイトの列を自分で追加することをお勧めします。。

  • したがって、最初(1984年)から変更されていない場合、CIの最適な候補は、複数列の一意のリレーショナルキーです(確かにあなたのものとは言えませんが、確かにそのように見えます)。

  • そして、単調に増加するキー(IDENTITY、DATETIME)をNCIに配置します。

  • CIは単一のストレージ構造であり、(そうでない場合は)ヒープを排除することにも注意してください。CIBツリーはリーフレベルの行と結合しています。リーフレベルエントリ行です。これにより、すべてのアクセスで読み取りが1つ少なくなります。

    • したがって、NCI+ヒープがCIよりも高速になる可能性はありません。物理法則に反するMSの世界でのもう一つの一般的な神話:Bツリーをナビゲートし、すでにいる1つの場所に書き込むことは、別のストレージ構造に行を追加で書き込むよりも高速である必要があります。しかし、MicroSoftiesは魔法を信じており、物理法則を停止しています。
  • 学習して使用する必要のある機能は他にもたくさんあります。この投稿を少し完全にするために、少なくともFILLFACTORとRESERVEPAGEGAPについて説明します。理解するまで、これらの機能を使用しないでください。すべてのパフォーマンス機能には、理解して受け入れる必要のあるコストがかかります。

  • CIは、ページレベルとエクステントレベルの両方で自動トリミングされ、無駄なスペースはありません。PageSplitsは監視対象であり(ランダム挿入のみ)、FILLFACTORとRESERVEPAGEGAPによって簡単に調整できます。

  • また、クラスター化されたインデックスのSOサイトを読んでください。ただし、上記のすべてに注意してください。最初の2つのパラ。

あなたの特定のケース

  • 必ず、代理キー(Idiot列)を削除し、それらを真の自然なリレーショナルキーに置き換えてください。サロゲートは常に追加のキーとインデックスです。それは忘れてはいけない価格です。

  • CompanyIdentifier + DepartmentIdentifier+[uniquiefier]はまさに私が話していることです。ここで、それらはすでにINTであり、非常に高速であることに注意してください。したがって、NUMERIC(10,0)iotキーを追加するのは非常にばかげています。Id1バイトまたは2バイトの列を使用して、一意性を強制します。

  • これが正しければ、パーティションライセンスは必要ないかもしれません。

  • CompanyIdentifier + DepartmentIdentifier + [uniquifier]は、定期的に一括削除/挿入を実行するコンテキストで、CIの最適な候補です(投稿したもの以外はデータベースについて何も知りません)。上記の詳細。

    • 他の人が述べていることに反して、これは良いことであり、CIを断片化することはありません。たとえば、20の会社があり、データの5%を構成する1つを削除するとします。適度に隣接していたそのPageChain全体は、現在、隣接していて無傷のFreePageChainに追いやられています。正確には、断片化の単一のポイントがありますが、単語の通常の使用という意味での断片化はありません。そして、振り返って大量挿入を実行した場合、データはどこに行くと思いますか?そうです、削除された行とまったく同じ物理的な場所です。また、FreePageChainは、一度にPageChain、エクステント、ページに移動します。
  • しかし、憂慮すべきことは、CIが一意であるという要求について知らなかったことです。MicroSoftiesがゴミを書くのは悲しいことですが、それぞれの単純化されたルールがなぜ/何に基づいているのかはわかりません。コア情報ではありません。一意でないCIの正確な症状は、DROP / CREATE CIの直後にテーブルが非常に高速になり、時間の経過とともに遅くなることです。優れたUniqueCIはその速度を維持し、速度が低下するまでに1年かかります(私の大規模でアクティブな銀行データベースでは2年)。

  • 4時間は、10億行にとって非常に長い時間です(エンタープライズプラットフォームでは、6列のキーを使用して160億行のCIを3分で再作成できます)。しかし、いずれにせよ、それはあなたがそれを定期的な毎週としてスケジュールするか、メンテナンスを要求しなければならないことを意味します。

  • WITH SORTED_DATAオプションを使用しないのはなぜですか?ドロップする前に、データはソートされていませんか?このオプションは、CIの非リーフページを書き換えますが、リーフページ(行を含む)は書き換えません。これは、データが並べ替えられたと確信できる場合にのみ実行できます。このオプションを使用しないと、すべてのページが物理的な順序で書き換えられます。

さあ、親切にしてください。20の質問をする前に、少し読んで、ここで定義したすべての問題を理解してください。

于 2010-12-02T04:24:08.150 に答える
0

私は最後の少し、いくつかのetlのもので遊んでいます。jsutを定期的にテーブルに挿入し、挿入の前後にインデックスを削除して再読み込みし、mergeステートメントを試し、最後にssisを試しました。私はssisで売られています。ちょうど昨日、ssisに挿入を処理させることで、etlプロセス(〜2400万レコード、〜6gb)を1回の実行あたり〜1-1 1/2時間から〜24分に短縮することができました。

高度なサービスを使えば、ssisを使えるはずだと思います。

于 2010-09-17T15:33:25.167 に答える