2016-09-01 5 views
0

私はSQL Server Management Studioのは、以下のストレージ統計を示すテーブル[ExampleSource]持っている:重複するテーブルのサイズが元のサイズよりずっと小さいのはなぜですか?

  • インデックス・スペース:58メガバイト
  • 行数:28269319
  • データ容量:4567メガバイト

さまざまなインデックス設定をベンチマークする目的で、次のコマンドを使用してテーブルをコピーしました。

SELECT * 
INTO [ExampleSource_Test] 
FROM [ExampleSource] 

クエリが終了するとすぐに驚くべきことに気付きました。新しいテストテーブル内のデータのサイズを劇的に小さくなっていた:

  • インデックス・スペース:0.016メガバイト
  • 行カウント:28269319
  • データ容量:2820メガバイト

新しいテーブルを持っています同じデータ、インデックス/プライマリキーはありません。

  • インデックススペース:22.227メガバイト
  • 行数:28269319
  • データ容量:2820メガバイト
私は次のような結果と新しいテストテーブルに(オリジナルと同じ)、主キーを追加しました

キーを追加してもデータスペースが増えるわけではありません。 - 千一般的には数時間で

CREATE TABLE [dbo].[ExampleSource] 
(
    [C1] [bigint] NOT NULL, 
    [C2] [nvarchar](9) NOT NULL, 
    [C3] [nvarchar](5) NOT NULL, 
    [C4] [int] NOT NULL, 
    [C5] [nvarchar](1) NOT NULL, 
    [C6] [int] NOT NULL, 
    [C7] [bit] NOT NULL, 
    [C8] [date] NULL, 
    [C9] [decimal](29, 9) NULL, 
    [C10] [nvarchar](max) NULL, 
    [C11] [nvarchar](1) NULL, 
    [C12] [decimal](29, 9) NULL, 
    [C13] [nvarchar](3) NULL, 

    CONSTRAINT [PK_ExampleSource] 
     PRIMARY KEY CLUSTERED ([C2] ASC, [C3] ASC, [C4] ASC, [C5] ASC, [C6] ASC, [C1] DESC) 
     WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
      IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, 
      ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] 

元のテーブルには時間をかけて多くの行挿入の結果である:それは場合に役立ちます。ここ

は、テーブル構造です。更新や削除はありません。私は元のテーブル(インデックスとデータの両方)とのこの劇的な空間の違いをどのように説明しているのだろうか?私は、一度にすべてをコピーするときにSQL Serverが多くの最適化/データの再編成を行っていることを推測していますが、なぜ元のテーブルに無駄なスペースがあったのかをよく説明しています。この肥大化を防ぐためにテーブル上で時折実行する必要のあるメンテナンスはありますか?

+0

サイドノート: 'nvarchar(1)'は無駄です。代わりに 'nchar(1)'を使用してください。最大1文字しか格納できないので、これを可変長カラムにするには、行ごとに2バイトのオーバーヘッドを追加するだけです(代わりに 'nchar(1)'を使用してもかまいません)。 'nvarchar(3) 'と同じです –

+0

marc_s、私はあなたのポイントについては、nvarchar(1)を参照してください。ただし、ストレージの観点からのみ、同じロジックがnvarchar(3)に適用されます。可変長アイテムがある場合は、ncharを使用したくありません。空白をトリミングするのは面倒です。 – c31983

+0

合意しましたが、90%+常に1〜3文字の長さの文字列を保存すると、その価値があります。 –

答えて

0

考えられる原因の1つは、元の表に1つ以上の可変長列がドロップされている可能性が考えられます。この場合、DBCC CLEANTABLE

第二の可能な理由は、断片化され使用しようと、クエリでそれをチェックしてみてください:

select a.index_id, name, avg_fragmentation_in_percent 
    from sys.dm_db_index_physical_stats (DB_ID(N'YourDatabase'), OBJECT_ID(N'ExampleSource'), NULL, NULL, NULL) a 
    join sys.indexes AS b ON a.object_id = b.object_id AND a.index_id = b.index_id 

いくつかのインデックスが断片化のために、それらを再編成した場合:

ALTER INDEX Index_name on Table_Name REORGANIZE WITH (LOB_COMPACTION=ON) 

の場合これはあまり役に立ちません。「ALTER INDEX REBUILD」を使用してください(最後の選択肢としてインデックスを削除して再作成してください)。

+0

テーブル構造は最初に作成されてから変更されていません。私はDBCC CLEANTALBEを試してみたいと思っていますが、あなたの答えにリンクされている記事では、「日常的なメンテナンス作業として実行すべきではない」と述べています。 – c31983

+0

インデックスが断片化されている可能性があります(回答を編集したばかりです)。これは(まれに)新しい行を追加するだけでも可能です。 – OlegAxenow

+0

編集した質問のクラスタード・インデックスを見てから、挿入中にページが分割されていることが原因である可能性が非常に高いと思います。 – OlegAxenow

関連する問題