如何在重建超大表的索引時保留較小的事務日誌文件
我需要我能獲得的所有幫助才能成功重建索引。特別是關於事務日誌管理的專家建議。
背景
目標數據庫是在聚集列儲存索引 (CCIX) 中託管 3 個大表的 DW 數據庫。最大的表叫Analog。它擁有約 370 億行和約 600 GB 的高壓縮數據。根據我們使用較小表的初步估計,150 GB 的 CCIX 表可以擴展到 5 TB,因此我們為這次重建提供了額外的 29 TB。
- SQL Server 企業版 2016
- 恢復模式 = 簡單
為什麼我們必須這樣做?
在我們的 ETL 服務的第一個版本中,數據在載入到 CCIX 之前不會先合併和排序。這導致 CCIX 的非最佳使用,因為許多行段在壓縮之前沒有完全填充。最佳段必須壓縮 1,0485,76 行,並且必須按時間排序,這樣基於時間的查詢才能在 sql server 中獲得最多的行組消除,並且要處理的段更少。我們正在學習更多的 CCIX,因為有更多的文件可用。
我的對齊摘錄在這裡 https://drive.google.com/file/d/0BzGLNskaj70UQUtZYW9CZF9iUUk/view?usp=sharing
新的 ETL 保證數據在載入到 CCIX 之前及時合併和排序。所以未來的載入將被排序,我們在這里關注在首次載入期間載入的現有數據。
有關完整的案例描述,請閱讀此處。 https://drive.google.com/open?id=0BzGLNskaj70URmZURlVDWVNYd2M
這是我們的第二次嘗試,儘管新腳本具有基於分區的索引重建,但我可以看到日誌文件仍在堆積。我們需要控制這一點。
我的問題是:
- 我已經執行了第二次嘗試(正在進行中),是否可以檢查哪些分區已經處理和排序?我在重建腳本中有 OFFLINE = ON 。
- 當基於分區的索引重建正在進行時,我們如何管理事務日誌的大小?如果可能,我們需要檢查並定期截斷每個分區。
- 由於日誌文件空間不足,索引重建最初失敗。我們添加了一個新的日誌文件並使用了一個單獨的磁碟。但是我們如何確保在第二次執行中不會再次發生這種情況?基於分區的重建是否足以保證我們可以成功重建?
感謝你的幫助。
按分區重建腳本(第二次嘗試) - 進行中
用時:17 小時 34 分鐘
--create a new clustered row index (CRI) CREATE CLUSTERED INDEX [Analog_ColumnStoreIndex] ON [dbo].[Analog] ( [LogTime] ASC, [CTDIID] ASC, [WindFarmId] ASC, [StationId] ASC ) WITH ( DROP_EXISTING = ON, PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, ONLINE = OFF ) ON [AnalogMonthlyPScheme]([LogTime]) GO
我會一次處理這個分區。在高水平:
- 使用分區聚集行儲存索引創建一個新的空目標表
- 使用未分區的聚集列儲存索引創建工作表
SWITCH
從源表到工作表的分區 1- 使用將工作表轉換為行儲存聚集索引
DROP_EXISTING
- 向工作表添加一個
CHECK
約束,該約束涵蓋分區 1 中的值範圍SWITCH
工作表進入目標表的分區 1- 放下空工作台
- 從第 2 步開始重複下一個分區
- 處理完所有分區後,刪除原始表並重命名新表
這最大限度地利用了最少記錄的操作,最小化了工作空間,並允許在必要時在分區之間清除事務日誌。
展示
分區
CREATE PARTITION FUNCTION [AnalogMonthlyP] (datetime2(0)) AS RANGE RIGHT FOR VALUES( N'2014-09-01T00:00:00.000', N'2014-10-01T00:00:00.000', N'2014-11-01T00:00:00.000', N'2014-12-01T00:00:00.000', N'2015-01-01T00:00:00.000', N'2015-02-01T00:00:00.000', N'2015-03-01T00:00:00.000', N'2015-04-01T00:00:00.000', N'2015-05-01T00:00:00.000', N'2015-06-01T00:00:00.000', N'2015-07-01T00:00:00.000', N'2015-08-01T00:00:00.000', N'2015-09-01T00:00:00.000', N'2015-10-01T00:00:00.000', N'2015-11-01T00:00:00.000', N'2015-12-01T00:00:00.000', N'2016-01-01T00:00:00.000', N'2016-02-01T00:00:00.000', N'2016-03-01T00:00:00.000', N'2016-04-01T00:00:00.000', N'2016-05-01T00:00:00.000', N'2016-06-01T00:00:00.000', N'2016-07-01T00:00:00.000', N'2016-08-01T00:00:00.000', N'2016-09-01T00:00:00.000', N'2016-10-01T00:00:00.000', N'2016-11-01T00:00:00.000', N'2016-12-01T00:00:00.000', N'2017-01-01T00:00:00.000', N'2017-02-01T00:00:00.000', N'2017-03-01T00:00:00.000', N'2017-04-01T00:00:00.000', N'2017-05-01T00:00:00.000', N'2017-06-01T00:00:00.000', N'2017-07-01T00:00:00.000', N'2017-08-01T00:00:00.000', N'2017-09-01T00:00:00.000', N'2017-10-01T00:00:00.000', N'2017-11-01T00:00:00.000', N'2017-12-01T00:00:00.000', N'2018-01-01T00:00:00.000', N'2018-02-01T00:00:00.000', N'2018-03-01T00:00:00.000', N'2018-04-01T00:00:00.000', N'2018-05-01T00:00:00.000', N'2018-06-01T00:00:00.000', N'2018-07-01T00:00:00.000', N'2018-08-01T00:00:00.000', N'2018-09-01T00:00:00.000', N'2018-10-01T00:00:00.000', N'2018-11-01T00:00:00.000', N'2018-12-01T00:00:00.000'); CREATE PARTITION SCHEME [AnalogMonthlyPScheme] AS PARTITION [AnalogMonthlyP] ALL TO ([PRIMARY]);
數字表設置(如果需要)
WITH Ten(N) AS ( SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 ) SELECT TOP (10000000) n = IDENTITY(int, 1, 1) INTO dbo.Numbers FROM Ten T10, Ten T100, Ten T1000, Ten T10000, Ten T100000, Ten T1000000, Ten T10000000; ALTER TABLE dbo.Numbers ADD CONSTRAINT PK_dbo_Numbers_n PRIMARY KEY CLUSTERED (n) WITH (SORT_IN_TEMPDB = ON, MAXDOP = 1, FILLFACTOR = 100);
源表和數據
-- Source table currently partitioned clustered columnstore CREATE TABLE [dbo].[Analog] ( LogTime datetime2(0) NOT NULL, CTDID integer NOT NULL, WindFarmId integer NOT NULL, StationId integer NOT NULL, INDEX [Analog_ColumnStoreIndex] CLUSTERED COLUMNSTORE ) ON [AnalogMonthlyPScheme](LogTime); -- Some test data INSERT dbo.Analog WITH (TABLOCKX) (LogTime, CTDID, WindFarmId, StationId) SELECT DATEADD(SECOND, N.n, '20140801'), CHECKSUM(NEWID()), CHECKSUM(NEWID()), CHECKSUM(NEWID()) FROM dbo.Numbers AS N -- ten million rows OPTION (MAXDOP 1);
目標台和工作台
-- The final table we want - partitioned rowstore clustered index CREATE TABLE [dbo].[AnalogNew] ( LogTime datetime2(0) NOT NULL, CTDID integer NOT NULL, WindFarmId integer NOT NULL, StationId integer NOT NULL, INDEX CCIX_Analog CLUSTERED (LogTime, CTDID, WindFarmId, StationId) ) ON [AnalogMonthlyPScheme](LogTime); -- Working table CREATE TABLE dbo.AnalogSwitch ( LogTime datetime2(0) NOT NULL, CTDID integer NOT NULL, WindFarmId integer NOT NULL, StationId integer NOT NULL, INDEX CCI CLUSTERED COLUMNSTORE );
分區 1
-- Process the first partition ALTER TABLE dbo.Analog SWITCH PARTITION 1 TO dbo.AnalogSwitch; -- Optional, may help parallel plan CREATE STATISTICS s ON dbo.AnalogSwitch (LogTime); -- Convert to rowstore clustered index CREATE CLUSTERED INDEX CCI ON dbo.AnalogSwitch (LogTime, CTDID, WindFarmId, StationId) WITH (DROP_EXISTING = ON); -- Specify data range ALTER TABLE dbo.AnalogSwitch ADD CONSTRAINT CK CHECK (LogTime >= '20140801' AND LogTime < '20140901'); -- Move to target table ALTER TABLE dbo.AnalogSwitch SWITCH TO dbo.AnalogNew PARTITION 1; -- Recreate switch table DROP TABLE dbo.AnalogSwitch; CREATE TABLE dbo.AnalogSwitch ( LogTime datetime2(0) NOT NULL, CTDID integer NOT NULL, WindFarmId integer NOT NULL, StationId integer NOT NULL, INDEX CCI CLUSTERED COLUMNSTORE );
分區 2
-- Process the second partition ALTER TABLE dbo.Analog SWITCH PARTITION 2 TO dbo.AnalogSwitch; -- Optional, may help parallel plan CREATE STATISTICS s ON dbo.AnalogSwitch (LogTime); -- Convert to rowstore clustered index CREATE CLUSTERED INDEX CCI ON dbo.AnalogSwitch (LogTime, CTDID, WindFarmId, StationId) WITH (DROP_EXISTING = ON); -- Specify data range ALTER TABLE dbo.AnalogSwitch ADD CONSTRAINT CK CHECK (LogTime >= '20140901' AND LogTime < '20141001'); -- Move to target table ALTER TABLE dbo.AnalogSwitch SWITCH TO dbo.AnalogNew PARTITION 2; -- Recreate switch table DROP TABLE dbo.AnalogSwitch; CREATE TABLE dbo.AnalogSwitch ( LogTime datetime2(0) NOT NULL, CTDID integer NOT NULL, WindFarmId integer NOT NULL, StationId integer NOT NULL, INDEX CCI CLUSTERED COLUMNSTORE );
…等等。這是相當簡單的腳本。