【问题标题】:Index performance while doing insert插入时的索引性能
【发布时间】:2015-05-21 00:33:21
【问题描述】:

我有一个有 4 列的表,我在这个表上有 3 个索引:

   CREATE TABLE [dbo].CustomerInfo(
        ID [int] IDENTITY(1,1) NOT NULL,
        UserHashID [varchar](20) NOT NULL,
        ShippingID [int] NOT NULL,
        Received [bit] NOT NULL,
     CONSTRAINT [PK_ID] PRIMARY KEY CLUSTERED 
    (
        [ID] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    ) ON [PRIMARY]

CREATE NONCLUSTERED INDEX [IDX_CustomerInfo_ShippingID] ON [dbo].[CustomerInfo]  (  [ShippingID] 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]

CREATE NONCLUSTERED INDEX [IDX_CustomerInfo_UserHashID] ON [dbo].[CustomerInfo]  (  [UserHashID] 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]

CREATE NONCLUSTERED INDEX [IDX_CustomerInfo_UserHashIDShippingID] ON [dbo].[CustomerInfo]  (    [UserHashID] ASC,   [ShippingID] 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]

我插入了大约 4-5 百万条记录,这个过程大约需要 45 分钟。我意识到如果我删除索引,插入速度会更快(2-3 分钟)。

想知道删除索引、插入并在插入完成后重建索引是否有任何副作用。与启用索引相比,整个过程可能需要 5 分钟,而如果启用索引则需要 45 分钟。

【问题讨论】:

标签: sql-server tsql indexing


【解决方案1】:

不,删除索引、执行插入和在插入完成后重新构建索引没有副作用(假设在执行插入时没有其他东西需要访问表)。

这是很常见的模式。

[话虽如此,我对具有 4 列和 3 个索引的表的时差感到惊讶。你能发布你的架构和索引定义吗]

正如@PJ8912 所指出的,事务日志记录可能会有所不同,具体取决于您备份事务日志的频率。

更新:不相关,但是这个索引

CREATE NONCLUSTERED INDEX [IDX_CustomerInfo_UserHashID] 
    ON [dbo].[CustomerInfo]  ([UserHashID] ASC)

是多余的,因为它被这个索引覆盖:

CREATE NONCLUSTERED INDEX [IDX_CustomerInfo_UserHashIDShippingID] 
    ON [dbo].[CustomerInfo]  ([UserHashID] ASC, [ShippingID] ASC)

【讨论】:

  • Mitch,我已经添加了表和索引架构。此外,大多数时候没有其他应用程序访问此表,因此正如您所提到的,删除索引、执行插入并在插入完成后重新创建索引应该是要走的路。但是,有时我有两个应用程序访问此表。这种情况有什么解决办法吗?我仍然可以删除索引,进行插入并再次重新创建索引吗?有什么办法可以在插入时锁定此表?谢谢
【解决方案2】:

根据事务日志记录的级别,TLogs 可能会定期重新创建索引而填满。如果您截断索引以消除它们,则不会记录该操作。

创建新索引后,执行计划的统计信息可能不是最新的。您可能希望使用 FULL SCAN 模式更新统计信息。

【讨论】:

  • “创建新索引后执行计划的统计信息可能不是最新的” - 我不确定这是否正确。
  • 也许我在平局上太快了(但可以有不同的统计设置)。我的建议是查看性能是否是一个问题,并查看 TLogs 是否会迅速变大。我确实认为删除和创建索引是一种很好的做法。
  • 在大量插入低于统计信息更新阈值后,统计信息可能不是最新的。
  • 感谢 PJ8912。我将检查事务日志的设置。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-31
  • 2023-04-04
  • 2015-08-08
  • 1970-01-01
  • 2011-03-19
  • 1970-01-01
相关资源
最近更新 更多