約30億行のディスク容量約104 GBを占めるヒープテーブルがあります。このテーブルの[WeekEndingDate
]列にクラスター化インデックスを作成しようとしています。データファイルには約200 GBの空き容量があり、tempdbには約280 GBの空き容量があります。
私は2つの異なる方法を試しました。最初に、次のコマンドを使用してテーブルに直接インデックスを作成しました。
CREATE CLUSTERED INDEX CX_WT_FOLD_HISTORY
ON WT_FOLD_HISTORY (WeekEndingDate ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = ON,
IGNORE_DUP_KEY = OFF
, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON,
DATA_COMPRESSION = PAGE)
SORT_IN_TEMPDB = ON
とOFF
の両方で試しました。 ON
を使用するとtempdbがいっぱいになり、OFF
でデータドライブがいっぱいになります。
他の方法は、必要なインデックスで新しい空のテーブルを作成し、レコードをヒープから新しいテーブルに挿入することでした。データドライブがいっぱいになった後も、これは失敗しました。
何をすべきかに関するその他の提案。私が読んだほとんどのことは、インデックスを作成するときにワークスペースとして使用するには、テーブルの約1.2倍のサイズが必要だと述べています。私はそれよりはるかに多く持っていますが、それでも失敗します。任意の提案をいただければ幸いです。
これが私の元のヒープテーブル構造です。
CREATE TABLE [dbo].[WT_FOLD_HISTORY](
[WeekEndingDate] [varchar](50) NULL,
[Division] [varchar](50) NULL,
[Store] [varchar](50) NULL,
[SKUNumber] [varchar](50) NULL,
[UPC] [varchar](50) NULL,
[SalesUnits] [varchar](50) NULL,
[SalesCost] [varchar](50) NULL,
[SalesRetail] [varchar](50) NULL,
[InventoryUnits] [varchar](50) NULL,
[InventoryCost] [varchar](50) NULL,
[InventoryRetail] [varchar](50) NULL,
[OnOrderUnits] [varchar](50) NULL,
[OnOrderCost] [varchar](50) NULL,
[OnOrderRetail] [varchar](50) NULL,
[ReceiptUnits] [varchar](50) NULL,
[ReceiptCost] [varchar](50) NULL,
[ReceiptRetail] [varchar](50) NULL,
[PermanentMarkdowns] [varchar](50) NULL,
[ReturnsToVendor] [varchar](50) NULL,
[POSMarkdowns] [varchar](50) NULL,
[TimeFK] [smallint] NULL,
[LocationFK] [int] NULL,
[ItemFK] [int] NULL
) ON [AcademySports_DataFG1]
ディスク容量が短期的に必要な場合、1つのオプションは次のとおりです。
注:他の人が示唆しているように、問題のテーブルから非クラスター化インデックスを一時的に削除するような場合にのみ、これを行います。とにかく、非クラスター化インデックスをすべて再構築する必要があるため、クラスター化インデックスの追加をより速く行うことができます(クラスター化インデックスが配置されている場合、インデックスキーはテーブル自体の行を見つけるために使用されます)。 。
それは実際には別のポイントです。クラスター化インデックスのキーの幅はどれくらいですか?非クラスター化インデックスがあり、クラスター化インデックスのキーがヒープへのポインターよりも大幅に広い場合、非クラスター化インデックスは、クラスター化インデックスの作成後により多くの領域を消費します。
クラスターキーが複数の列、または1つの大きな列(たとえば、平均長が25以上のvarchar
列)で構成される場合は、代わりに代理キー(通常は単調増加する値)を検討することができます。 、最高のINSERT
パフォーマンス。
あなたのスペースを埋めているのはあなたのメガソートです(あなたは104Gbのすべてを全体でソートしようとします)ので、より小さな部分でソートすることで解決できると思います。新しいクラスター化テーブルを作成し、次のような小さなチャンクにデータを挿入することをお勧めします。
declare @rowcount int = 1;
while @rowcount > 0
begin
delete top (5000)
from your_heap with(tablock)
output deleted.field1, ..., deleted.fieldN
into new_clustered_table;
set @rowcount = @@rowcount;
end;
この方法では、一度に5000行のみを並べ替えますが、唯一の問題は、並べ替えられた挿入を行わないため回避できないページ分割です。したがって、終了すると、new_clustered_tableはフラグメント化されますが、後で再構築できます。
簡単なヒント-クラスタ化インデックスを作成する前に、このヒープ上のすべての非クラスタ化インデックス(存在する場合)を削除することを検討してください。それらの非CIをそれらのインクルード列の詳細とともにスクリプト化し、クラスター化インデックスが正常に作成された後で、それらの定義を使用して後でそれらを再度作成できます。