2011-08-20 117 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索引并从头开始创建它。 –