插入速度恶化

时间:2012-08-13 05:56:38

标签: tsql indexing sql-server-2008-r2

基本问题是加载数据时插入率会下降。

  • 禁用所有索引但PK
  • 禁用FK约束。
  • 在插入
  • 之前,使用LINQ对PK进行数据排序

但插入速度仍在下降。

在加载期间,用户数量有限。所以不能取下PK。

数据按PK的顺序加载,但该索引仍然存在碎片。

Int,TinyInt,String的复合PK。

在加载重建索引之前,填充因子为100%。该表有另一个被禁用的索引。

现在有20,00行加载到表中,PK索引已经有4%的碎片。它继续碎片和加载速度恶化。使用DBCC SHOWCONTIG('docMVtext','PK_docMVtext')检查碎片

  • 扫描的页数................................:155
  • 扫描范围..............................:26
  • 范围开关..............................:25
  • 平均。每个页面的页数........................:6.0
  • 扫描密度[最佳数量:实际数量] .......:76.92%[20:26]
  • 逻辑扫描碎片..................:4.52%
  • 范围扫描碎片...................:96.15%
  • 平均。每页字节数.....................:54.9
  • 平均。页面密度(完整).....................:99.32%

范围扫描碎片很高,也许我应该打开第二个问题。

我认为它不是作为PK的一部分的varchar(600)值,因为有一个姐妹表docSVtext只在int tinyint上有PK并且遇到同样的问题。

通过备份还原从另一个数据库创建此数据库。需要相同的配置表,但不是相同的数据表。从数据表中删除数据并运行shrinkdb TRUNCATEONLY。

使用插入值(),(),()加载值。

认为值(),(),()可能正在改变顺序,因此将.NET更改为每行一个插入,并且即使按PK顺序插入数据,仍然会在PK上进行碎片化。

三次检查数据是否按PK的顺序插入。

在.NET应用程序中,我使用LINQ在插入之前对数据进行排序。在调试中,我回顾了40,它们都已正确排序。

甚至创建了一个带有iden的镜像表,然后是相同的三列。在该镜像表上使用相同的插入来验证插入顺序。当我选择按照iden排序的镜像表时,数据按排序顺序排列。这只是我插入由PK排序的数据的次要测试。

以下是表格定义。 (是的,我知道在第一段说明没有FK约束,这显示了FK约束。当我删除FK约束时没有帮助插入速度。)

USE [Gabe2a_ENCORE]
GO

/****** Object:  Table [dbo].[docMVtext]    Script Date: 08/12/2012 20:13:35 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[docMVtext](
    [sID] [int] NOT NULL,
    [fieldID] [tinyint] NOT NULL,
    [value] [varchar](600) NOT NULL,
 CONSTRAINT [PK_docMVtext] PRIMARY KEY CLUSTERED 
(
    [sID] ASC,
    [fieldID] ASC,
    [value] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = ON, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON, FILLFACTOR = 100) ON [PRIMARY]
) ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO

ALTER TABLE [dbo].[docMVtext]  WITH CHECK ADD  CONSTRAINT [FK_docMVtext_docFieldDef] FOREIGN KEY([fieldID])
REFERENCES [dbo].[docFieldDef] ([ID])
GO

ALTER TABLE [dbo].[docMVtext] CHECK CONSTRAINT [FK_docMVtext_docFieldDef]
GO

ALTER TABLE [dbo].[docMVtext]  WITH NOCHECK ADD  CONSTRAINT [FK_docMVtext_docSVsys] FOREIGN KEY([sID])
REFERENCES [dbo].[docSVsys] ([sID])
GO

ALTER TABLE [dbo].[docMVtext] CHECK CONSTRAINT [FK_docMVtext_docSVsys]
GO

令我困惑的是,在这个初始加载之后,我解析并索引文本以创建一个简单的全文搜索索引。要加载这些表,我在内存中使用相同的排序策略,并按PK的顺序插入,我得到PK的零碎片。我无法弄清楚在PK上获得这种碎片的初始负载有什么不同。

我知道人们不会相信这一点,但主要的瓶颈在第一张桌子上。

下面的第一个代码比第二个代码快10倍,表中有300,000行。在160万行中,第一行快30倍。在一开始就让我使用草率的@@ identity。

SQLcmd.CommandText = commandText + ";  SELECT SCOPE_IDENTITY() ";
sID = int.Parse((SQLcmd.ExecuteScalar().ToString()));


SQLcmd.CommandText = commandText;
rowsRet = SQLcmd.ExecuteNonQuery();
if (rowsRet == 1)
{
    commandText = "select @@identity from [docSVsys]";
    SQLcmd.CommandText = commandText;
    sID = int.Parse(SQLcmd.ExecuteScalar().ToString());
}

1 个答案:

答案 0 :(得分:1)

由于这是一个用于初始化的批量插入,我建议删除表中的所有索引。通过这样做,您可以尽快将数据导入服务器。之后,在数据加载完成后应用PK和非聚簇索引。 Sql server将能够同时处理所有数据的重新排列,而不是每次达到给定页面的填充因子。