4

クラスタ化されたGUIDフィールドとして主キーを持つテーブルがあります。NEWSEQUENTIALID()の代わりにを使用してGUIDを生成して いNEWIDます。残念ながら、このテーブルでは1日あたり約25k〜100kの挿入が見られるため、数時間以内に(デフォルト:クラスター化された)主キーインデックスは99%断片化されます。

もともとNEWIDはシーケンシャルIDを生成する代わりに使用していましたが、テーブルを再作成し、を使用してすべての行を再挿入した場合でもNEWSEQUENTIALID(主キー列のデフォルト値として指定した場合でも)、数回以内に99%程度の断片化が見られます。時間。(現在、このテーブルには約130万件のレコードが含まれています。

GUIDを整数の主キーに置き換えることを考えていましたが、それが機能するかどうかはわかりません。さらに、私たちのチームは今後、整数ではなく主キーにGUIDを使用するため、これを行うのに十分な賛同を得られるとは思いません。

このことを最適化しておくための私のオプションは何ですか?SQL Server Expressを使用しているため、SQL Agentにアクセスできません(したがって、定期的にメンテナンスプランを実行してインデックスを再構築することはできません)。

また、将来のある時点でこのデータベース/テーブルを分割する可能性が非常に高いため(データの量が多いため)、テーブルをマージするためにGUIDが必要になる可能性があります。

また、インデックス付きビューを使用することはできません。これは、結合に巻き戻すのが難しい内部選択があるためです。

4

4 に答える 4

7

私自身の個人的な経験ではGUID、クラスタリングキーとしてsを破棄すると、システム、特にインデックスの断片化に大きなプラスの影響を与える可能性があります。

私の新しいINT IDENTITYクラスタリングインデックスは、何ヶ月にもわたって毎日の本番環境で使用した後でも、断片化はほとんどありません。間違いなくそれだけの価値があります!

GuidSQL Serverのクラスタリングキーとしてデータ型を使用することは、ひどく悪い選択です-どちらの見方をしても...

このトピックに関するKimberlyTripp(Queen of Indexing)のブログ投稿の一部を参照してください。

そして、彼女がキーのクラスタリングのトピックについてブログに書いている他の何か....

于 2012-01-17T14:49:34.160 に答える
2

私は8年以上前(この記事の執筆時点)に開始されたスレッドをネクロしていることを完全に理解していますが、NEWID()、NEWSEQUENTIALID()、 "Ever-increasing-INTs"、および私が単に「ExpAnsiveUpdates」(「A」を使用)と呼んでいるもので、実際にはExp E nsive(「E」を使用)です。

最初に後者について説明しましょう。これはおそらくOPが抱えている本当の問題です...

わずかな違いがありますが、ページ分割の不要な作成とその結果の断片化に関してはそれほど重要ではありませんが、NEWSEQUENTIALIDと「Ever-increasingINTs」はどちらも同じように機能します...それ自体では、「良い」ページ分割(これも「悪い」ですが、それは別の議論の主題です)。したがって、Opが、完全にランダムなNEWIDから「増え続ける」NEWSEQUENTIALIDに切り替えても、作成されていた断片化の量に違いはないようだと述べた、最初に投稿された質問を参照してください。

その理由は、NEWSEQUENTIALIDに問題があるという事実ではありません(問題はありません)。断片化の問題は、新しい行が挿入されている可能性が高く(これにより、NEWSEQUENTIALIDによる断片化は発生しません)、それらの新しい行は、それらを更新するための別のプロセスを受けます。更新が「 ExpAnsive」では、行の可変幅の列の幅が広くなり、大量のページ分割が発生します。これは、かなり低いFILL FACTORでインデックスを作成した場合でも発生します。これは、INSERTがページに到達したためにページへの挿入を停止しないためです。 FILL FACTOR。代わりに、多数の挿入がほぼ100%いっぱいになるまでページに挿入され(挿入される行の幅に依存するページあたりの行数に応じて)、「増え続ける整数を使用しているかのように、実質的に断片化のない「良い」ページ分割。

したがって、これらの行をすべて連続したページに挿入すると、可能な限り100%近くまで埋められます。すべてが正常です...断片化はありません。ただし、挿入したばかりの行を更新する「挿入後処理」を実行します。「 ExpAnsive」ために行のサイズが大きくなった場合は、 KAAAA-BOOOOOM !!! それらの完全に完全なページはすべて分割されてしまいます。

このような拡張の最も一般的な原因の1つは、人々が「貧乏人の監査」を使用し、NULLからある値に変化する「Modified_BY」列を持っている場合です。その特定の問題を修正する方法はたくさんありますが、繰り返しになりますが、このスレッドと投稿の範囲をはるかに超えています。

NEWID()によって生成されたランダムなGUIDにギアをシフトする...それらを使用しない理由はたくさんありますが、あなたが信じさせられたものとはまったく逆に、断片化は実際にはそれらの1つではありません。私はそれを証明する非常に「アリスのレストランファッション」(たくさんのグラフィックとグラフィックの表記)でいくつかのプレゼンテーションをしました。この投稿に適した1時間以上のプレゼンテーションを作成するために、それはすべて、人々が犯し続けるいくつかの小さな、しかし致命的な間違いに要約されることをお伝えします...

  1. おそらく「ベストプラクティス」が主な問題であるため、彼らはREORGANIZEを使い続けています。彼らは、REORGANIZEが実際にGUIDに対して機能しないことに気づいていません。ページに余分なスペースを提供する代わりに、実際には余分なスペースを削除します。つまり、私の仲間のインデックスラングラーは、実際にはGUIDの断片化を永続化します。ランダムガイドでインデックスのメンテナンスを行う場合は、REORGANZEを使用しないでください。限目!!!ExpressまたはStandardEditionを使用している場合でもそうではありません。再構築するための時間、リソース、またはディスクスペースがない場合は、REORGANZEを使用して間違って行うよりも、ランダムGUIDでインデックスのメンテナンスを行わない方が実際には適切です。REBUILDができるようになるまで待ちます。

  2. ランダムなGUIDキー付きインデックスには低いFILLFACTORを設定する必要があります。それらを「0」のままにしておくことは、それらを再編成することとほぼ同じくらい悪いことです。もちろん、インデックスの行の幅、1日に挿入される行の数、およびランダムGUIDでのページ分割が完全にゼロ(「適切な」ものとは見なされない場合もあります!!!)を使用する期間によって異なります。インデックスでは、FILL FACTORを71、81、または91に設定するように指示します。これらすべてを「1」で終わらせる理由は、「ExpAnsive」の更新時にランダムGUIDを修正する必要があるためです。存在しません。これは、以下の項目#3です。

  3. 毎晩、ランダムなGUIDに基づくインデックスを確認する必要があります。「1」で終わるすべてのFILLFACTORを指定した理由は、それが論理フラグメンテーションの%として探しているものだからです。インデックス全体のほぼすべてのページが分割されるポイントにあるため、1%を超えるとすぐに、それらを再構築する必要があります。(私はこれらを「低しきい値再構築」と呼んでいます)。さて、混乱しないでください。すべてが正しく設定されていて、「ExpAnsive」更新がない場合、GUIDキーのクラスター化インデックスはページ分割や関連する断片化なしで数週間かかる可能性があり、はるかに狭い非クラスター化インデックスは文字通り断片化なしでMONTHSになります。

もう1つの大きな間違いは、もちろん「ExpAnsive」の更新です。それらはほぼすべてを殺しますが、驚くべきことに、ランダムGUIDは、上記と同じ手順を使用して、他のほとんどのものよりもはるかに優れた猛攻撃を実際に乗り越えます。

本当に必要なのは、「ExpAnsive」アップデートを修正して、「ExpAnsive」ではなくなるようにすることです。私が言ったように、それはこの投稿を待ち望んでいる全体の主題です。

于 2020-04-22T23:13:16.507 に答える
1

これは、挿入数が多いGuidインデックスで予想される動作です。ほとんどの場合、レコードが複数のソースによって生成され、個々のソースがお互いのつま先を踏まないようにする必要があるという理由だけで、 GUIDをキーとして選択します。ここでの例は、オフラインのモバイルデバイスです。現場の作業員は、接続されていないときに新しいレコードを作成する必要があるため、モバイルデバイスはGUIDをキーとして安全にレコードを作成できます。後でオンラインに戻ると、デバイスはキーの衝突を心配することなくデータベースと安全に同期できます。

単一のサーバーでGUIDを生成する場合は、通常、単純なID列を使用することをお勧めします。GUIDが本当に必要な場合でも、それらを含めることができます...クラスター化されたインデックスにそれらを使用することについて2度考えたいと思うかもしれません。guidでクラスター化する必要がある唯一の理由は、後でテーブルに戻って、そのguidに基づいて一度に1つのレコードを照会する場合です。あなたが見ている挿入率では、それはありそうもないようです。ただし、その場合は、インデックスの曲線因子を減らすことで、問題を軽減することができます。これにより、使用されるディスクスペースの量が増加します(そして、後でより多くのディスクシークを実行することを意味します)が、ページがより速くいっぱいになり、インデックスの再シャッフルの一部を回避できます。

整数ベースのキーが問題外である場合にここで確認するもう1つのオプションは、シーケンシャルGUIDです。これにより、独自性が維持されると同時に、断片化が少なくなります。

于 2012-01-17T14:51:13.490 に答える
-2

stackexchangeデータエクスプローラーでこの単純なクエリを見てください。最下位ではなく、GUIDの最上位newsequentialid()部分をインクリメントするように見えます。これは、あなたが見ている断片化の原因である可能性があります。

GUIDを使用する必要がある場合は、データベースの生成に依存するのではなく、コードを介してGUIDを生成し、挿入ステートメントで送信することを検討してください。「comb」手法を使用して、現在のタイムスタンプをGUIDの一部として使用し、最下位桁で増分します。


編集

..または、コードでそれらを生成したくない場合は、データベース内でこのようなことを行うことができます

CAST(CAST(NEWSEQUENTIALID() AS BINARY(10)) + CAST(GETDATE() AS BINARY(6)) AS UNIQUEIDENTIFIER)

上記のクエリに対するこの変更に従って、デフォルト値として

于 2012-01-17T14:18:23.987 に答える