And*_*rew 55 c# sql sql-server sql-server-2005
我的C#客户端将批量数据插入SQL Server 2005数据库时遇到了一些性能瓶颈,我正在寻找加快这一过程的方法.
我已经在使用SqlClient.SqlBulkCopy(它基于TDS)来加速通过线路的数据传输,这有很大帮助,但我仍然在寻找更多.
我有一个简单的表,看起来像这样:
CREATE TABLE [BulkData](
[ContainerId] [int] NOT NULL,
[BinId] [smallint] NOT NULL,
[Sequence] [smallint] NOT NULL,
[ItemId] [int] NOT NULL,
[Left] [smallint] NOT NULL,
[Top] [smallint] NOT NULL,
[Right] [smallint] NOT NULL,
[Bottom] [smallint] NOT NULL,
CONSTRAINT [PKBulkData] PRIMARY KEY CLUSTERED
(
[ContainerIdId] ASC,
[BinId] ASC,
[Sequence] ASC
))
Run Code Online (Sandbox Code Playgroud)
我在平均大约300行的块中插入数据,其中ContainerId和BinId在每个块中是常量,并且Sequence值是0-n,并且值是基于主键预排序的.
%Disk时间性能计数器花费大量时间在100%,因此很明显磁盘IO是主要问题,但我得到的速度比原始文件副本低几个数量级.
如果我:它有帮助吗?
- 根据我得到的答复,让我澄清一下:
Portman:我正在使用聚簇索引,因为当数据全部导入时,我需要按顺序依次访问数据.导入数据时,我并不特别需要索引.在执行插入时是否有任何优势来使用非聚簇PK索引而不是完全删除约束以进行导入?
Chopeen:数据是在许多其他机器上远程生成的(我的SQL服务器目前只能处理大约10个,但我希望能够添加更多).在本地计算机上运行整个过程是不切实际的,因为它必须处理50倍的输入数据才能生成输出.
Jason:我在导入过程中没有对表进行任何并发查询,我会尝试删除主键,看看是否有帮助.
Joh*_*hnB 19
以下是在SQL Server中禁用/启用索引的方法:
--Disable Index ALTER INDEX [IX_Users_UserID] SalesDB.Users DISABLE
GO
--Enable Index ALTER INDEX [IX_Users_UserID] SalesDB.Users REBUILD
Run Code Online (Sandbox Code Playgroud)
以下是一些可帮助您找到解决方案的资源:
使用SqlBulkCopy快速将数据从客户端加载到SQL Server
绝对看看NOCHECK和TABLOCK选项:
Por*_*man 18
你已经在使用SqlBulkCopy,这是一个好的开始.
但是,仅使用SqlBulkCopy类并不一定意味着SQL将执行批量复制.特别是,SQL Server必须满足一些要求才能执行有效的批量插入.
进一步阅读:
出于好奇,为什么你的指数设置如此?好像数据筒/ BinId /序列是很多更适合成为一个非聚集索引.您是否希望将此索引集群化?
我的猜测是,如果将该索引更改为非聚集,您将看到显着的改进.这有两个选择:
任何一个都可以加快插入速度而不会明显减慢读取速度.
以这种方式考虑 - 现在,你告诉SQL做一个批量插入,但是你要求SQL在你添加任何东西的每个表中重新排序整个表.使用非聚簇索引,您将按照它们进入的顺序添加记录,然后构建一个指示其所需顺序的单独索引.
您是否尝试过使用事务?
根据您的描述,让服务器将 100% 的时间提交到磁盘,似乎您在原子 SQL 语句中发送每一行数据,从而迫使服务器提交(写入磁盘)每一行。
如果您改为使用事务,则服务器只会在事务结束时提交一次。
如需进一步帮助:您使用什么方法将数据插入服务器?使用 DataAdapter 更新 DataTable,还是使用字符串执行每个句子?
jas*_*ldo -1
是的,你的想法会有所帮助。
如果加载时没有发生读取,请采用选项 1。
如果在处理过程中查询目标表,请采用选项 2。
@安德鲁
问题。您以 300 块为单位插入。您插入的总量是多少?SQL Server 应该能够非常快速地处理 300 个普通的旧插入。