2011-08-20 169 views
3

每天我從一些文本文件中使用BULK INSERT導入2,000,000行到SQL Server 2008中,然後執行一些後續處理來更新記錄。SQL Server 2008索引碎片問題

我在表上有一些索引來儘可能快地執行後處理,而在正常情況下,後處理腳本大約需要40秒才能運行。

但有時(我不知道什麼時候)後處理不起作用。在我提到的情況下,一小時後就不會完成!重建索引後,一切都很正常。

我應該怎麼做才能防止問題發生?

現在,我有夜間工作重建所有索引。爲什麼指數碎片增長到90%?

更新: 這裏是我的表,我導入文本文件到:

CREATE TABLE [dbo].[My_Transactions](
    [My_TransactionId] [bigint] NOT NULL, 
    [FileId] [int] NOT NULL, 
    [RowNo] [int] NOT NULL, 
    [TransactionTypeId] [smallint] NOT NULL, 
    [TransactionDate] [datetime] NOT NULL, 
    [TransactionNumber] [dbo].[TransactionNumber] NOT NULL, 
    [CardNumber] [dbo].[CardNumber] NULL, 
    [AccountNumber] [dbo].[CardNumber] NULL, 
    [BankCardTypeId] [smallint] NOT NULL, 
    [AcqBankId] [smallint] NOT NULL, 
    [DeviceNumber] [dbo].[DeviceNumber] NOT NULL, 
    [Amount] [dbo].[Amount] NOT NULL, 
    [DeviceTypeId] [smallint] NOT NULL, 
    [TransactionFee] [dbo].[Amount] NOT NULL, 
    [AcqSwitchId] [tinyint] NOT NULL 
) ON [PRIMARY] 

GO 

CREATE NONCLUSTERED INDEX [_dta_index_Jam_Transactions_8_1290487676__K1_K4_K12_K6_K11_5] ON [dbo].[Jam_Transactions] 
(
    [Jam_TransactionId] ASC, 
    [TransactionTypeId] ASC, 
    [Amount] ASC, 
    [TransactionNumber] ASC, 
    [DeviceNumber] ASC 
) 
INCLUDE ([TransactionDate]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
GO 

CREATE NONCLUSTERED INDEX [_dta_index_Jam_Transactions_8_1290487676__K12_K6_K11_K1_5] ON [dbo].[Jam_Transactions] 
(
    [Amount] ASC, 
    [TransactionNumber] ASC, 
    [DeviceNumber] ASC, 
    [Jam_TransactionId] ASC 
) 
INCLUDE ([TransactionDate]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
GO 

CREATE NONCLUSTERED INDEX [IX_Jam_Transactions] ON [dbo].[Jam_Transactions] 
(
    [Jam_TransactionId] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
GO 

回答

1

而是包括在夜間作業本表的,你爲什麼不賺指數維護(在此發表具體)的一部分的夜間進口工作,BULK INSERT和任何'後期處理'是什麼?

我們沒有足夠的信息知道爲什麼索引碎片增長很快。哪個指數?有多少指標?文件中數據的順序是什麼?

您也可以考慮在BULK INSERT語句中使用ORDER選項來更改插入數據的方式。這可能會使負載花費更長的時間,但它可以減少重新組織的需要。再次取決於源數據的順序和成爲碎片的索引。

最後,重建/不重建或重組/不重組索引的影響是什麼?你有沒有試過?也許它使得後處理運行更快,如果你重建,但可能只有碎片整理是必要的。雖然它可能會使後處理更快,那麼當天晚些時候在桌面上運行的查詢又如何呢?你有沒有對這些人做任何指標,看他們是否加速或放慢,取決於你在晚上做什麼?

+0

謝謝,主要問題是我在表上存在100,000,000條記錄,重建索引需要很長時間,所以似乎沒有重建所有索引(插入500,000條新記錄後)可能是最佳解決方案。 我有4個索引(PK Identity上的一個聚簇索引,以及TransactionTime,CardNumber和TransactionNumber上的3個非聚簇升序索引)。我所有的領域都是bigint。 –

+1

你應該看看這個表的分區,如果可能的話,你可能只能重建表的一部分。 – SqlACID

+0

@SqlACID打敗了我......當然聽起來像是分區的情況。 –

0

您的主表是否每天增長200萬行或者是否還有很多刪除發生?您可以批量插入臨時導入表並在插入主表之前進行處理嗎?您可以隨時使用提示來強制查詢中使用某些指標:

SELECT * 
FROM your_table_name WITH (INDEX(your_index_name)) 
WHERE your_column_name = 5 
+0

我不刪除任何記錄。我的步驟如下:1-從文本文件插入RAW數據表。 2-用戶批准。 3-過程批准的記錄。 4-將處理過的記錄插入另一個表中(RAW數據表中沒有任何更改)。 有時索引碎片的值很高,導致進程部分失敗。 –

+0

「失敗」你的意思是「緩慢」吧?有一個很大的區別。突然間,我不清楚碎片如何導致插入緩慢。碎片在哪裏?在原始表格上還是在目標表格上?你是在觀察緩慢問題之前還是之後檢查這種碎片?發生這種情況時,插入的數據有什麼不同?對於更具體的幫助,您需要提供更多關於我在問題中提出的問題(您觀察碎片的索引,文件中數據的性質)的更多詳細信息。 –

+0

「失敗」我的意思是2小時後它沒有完成,然後我就停止了!在正常情況下,花了30秒。 –

2

您是否嘗試過剛剛刷新統計這麼大的插入後:

UPDATE STATISTICS my_table 

我的大批量插入的經驗是,統計數據全部被破壞並且需要在之後刷新,這比運行REINDEX或索引REORDER要快得多。

另一種選擇是尋找到填充索引,你可能對你的索引也就是說,如果你的指數是沒有填充填充因子:

A, B, D, E, F 

,你插入值以C的CardNumber,然後你的指數將是這樣的:

A, B, D, E, F, C 

,因此是〜20%支離破碎,如果不是指定您的說,指數的填充因子15%,我們會看到它的樣子大致爲:

A, B, D, _, E, F 

(注意內部空的空間把大致的填充因子%的中間點不在末尾)

所以,當你真正插入C值是更接近於正確的,但它看到D只是與C交換,並且通常會在此時移動D。

除此之外,你確定碎片實際上是問題,因爲重新索引表的一部分被完全讀取並加載到內存中(只要它適合),因此你運行的任何查詢都會非常快。

0

我會嘗試在大量行插入之前離線索引,並在插入大量行之後將其重新聯機。與重新建立索引或執行刪除和創建索引相比,速度要快得多......區別在於索引是在那裏存儲數據,但索引當前未被使用,直到它被「離線」帶回「在線」。我有一個150萬行的插入過程,並且遇到了導致性能較差的非聚簇索引分片問題。走到形式99%的碎裂使用MSSQL離線在線索引選項0.14%....

代碼示例:

ALTER INDEX idx_a ON dbo.tbl_A 
REBUILD WITH (ONLINE = OFF); 

OFF之間進行切換就和你是好去....

+0

這實際上不會使索引脫機。它使用離線表重建索引,即沒有其他過程可以使用它。當然,這最終幾乎沒有碎片,因爲它在後臺執行DROPS索引並從頭開始創建它。 –