web-dev-qa-db-ja.com

ヒープの場合、テーブルはメリットがありますか

約1.500.000行のログテーブルがあります。主キーは昇順のIDであり、クラスター化インデックスは主キーにあります。 ID値は自動生成されます=>レコードは常に最後に追加されます。行の平均サイズは1570バイトです。

新しい行が頻繁に追加されるため、多くのページ分割があります。行は更新/削除されず、テーブルに非クラスター化インデックスがあるため、行を選択できます。ページ分割により、クラスター化インデックスは常に65%以上に断片化されます。

テーブルがクラスター化インデックスを削除してヒープテーブルにするメリットがあるのでしょうか。

これは私のテーブル+非クラスター化インデックスがどのように見えるかです:

CREATE TABLE [dbo].[LogEntry](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[Application] [varchar](20) NOT NULL,
[EntityFullName] [varchar](80) NOT NULL,
[Action] [int] NOT NULL,
[UserName] [varchar](25) NOT NULL,
[TimeStamp] [datetime] NOT NULL,
[EntityId] [varchar](50) NOT NULL,
[WhatChanged] [nvarchar](max) NULL,
CONSTRAINT [PK_LogEntry] PRIMARY KEY CLUSTERED(     
   [Id] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 100) ON [PRIMARY] ) 
ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]


CREATE NONCLUSTERED INDEX [ID_Application_Entity_FullName_TimeStamp] ON [dbo].[LogEntry]
(
    [Application] ASC,
    [EntityFullName] ASC,
    [TimeStamp] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = OFF) ON [PRIMARY]
GO

pdate:誰かが私の後ろで自動縮小を有効にしていました=>これが断片化の原因になります

これはコメント/質問として始まりましたが、長くなりましたので、ここに移動しました:

私はこの質問に本当に感動しました。 150万行は実際にはそれほど大きくありません。そして、アイデンティティの背後にあるポイントは、それが増え続けるということです。それがCLである場合、ページの中央に挿入するべきではありません。確かに、表示されている断片化のレベルを引き起こすほど頻繁ではありません。

質問の組み合わせ:

IDENTIY_INSERTSを実行していますか?基本的にID値を指定する必要がありますか?または、範囲の中央に挿入するように、ある時点でIDを再設定しましたか?

通常、挿入を行う場合は次のようになります。

5 6 7 8 < Next insert goes here >

しかし、このようなものがある場合(次のID値が4であると想定)

 1 2 3 < Next insert goes here > 100 101  

次に、かなりの数のページ分割が表示される可能性があります。しかし、通常のことではありません。

データベースを縮小する可能性はありますか? Auto_shrinkまたは縮小するメイントプラン/ジョブ?その場合、クラスター化インデックスではなく、断片化を引き起こしているのは縮小です。

一般に、HEAPに問題はなく、INSERTの方が高速になる可能性があります。それらに対する私の最大の懸念は、大量の削除または更新を行っている場合(そうではないと言う場合)です。これらの場合、スペースリークが発生し、サイズが数GBであるが行が0のテーブルが作成される可能性があります。

実際の回答

ログファイルがあり、挿入しているだけの場合は、PKを削除してパフォーマンスがどのようになるかを確認できます(もちろん、最初にテスト環境で)。ワークロードを使用していくつかのテストを実行し、状況を確認したら、運用環境に変更を加え、しばらく監視します。 ID列を完全に削除することを検討することもできます。

その収縮をチェックしてください。それはキラーです。

5
Kenneth Fisher

SQL Serverのインデックスに対するThomas Kejserの見解を確認すると興味深いかもしれません。クラスター化インデックスは非常に便利ですが、ヒープを保持する理由がある場合があります。たとえば、この投稿を読んでください:

http://kejser.org/clustered-indexes-vs-heaps/

特にトピックを見てください:多くのINSERTアクティビティを持つフラグメンテーション傾向テーブル

このトピックは、断片化に直面している問題を正確に説明しているようです。そう...

代替案を検討してください:十分に「ランダムな」キー(GUIDなど)とを選択するインデックス付け戦略では、そのキーをクラスターインデックスを盲目的に宣言する代わりに、代わりに、テーブルをヒープとして残し、GUIDに古き良き独自の非クラスター化キーインデックスを置くだけです。 INSERTによるテーブルの増加の大部分はヒープに送られ、ヒープは適切にいっぱいになり、断片化されません。

Technetからの別のコメント: http://technet.Microsoft.com/en-us/library/hh213609.aspx

「データアーキテクトは、データが常に非クラスター化インデックスを通じてアクセスされ、RIDがクラスター化インデックスキーよりも小さい場合に、ヒープを使用することがあります。」

それらの投稿はあなたの問題について考える何かを与えるかもしれません。

1
RLF