为什么SQL服务器插入这么慢?

时间:2009-11-16 17:07:44

标签: sql sql-server-2005

我正在尝试将内存数据行插入到SQL Server Express 2005上的表中。它在我看来非常缓慢地运行 - 每1000行插入大约5秒。我只是使用基本的“INSERT INTO”命令。缓慢不依赖于表数据 - 对于具有一个int列且没有索引的表,它仍然很慢。它与我的软件无关 - 它在Management Studio的循环中运行缓慢。没有其他东西可以同时访问数据库。在3Ghz Xeon(我知道的旧版本)上,执行大约需要10秒钟:

declare @i int  
set @i = 0  
set nocount on  
while @i < 2000  
begin  
insert into testdb(testcolumn)  
values (1)  
set @i = @i + 1  
end  

是否有更好的方法来插入批量内存数据而不是在INSERT上循环?或者我应该在SQL Server中更改一些配置?

7 个答案:

答案 0 :(得分:24)

您在自己的交易中执行每个插入。

SQL Server中的开始和提交交易非常

将所有内容封装到一个事务块中:

declare @i int
set @i = 0
set nocount on
BEGIN TRANSACTION
while @i < 2000
begin
insert into testdb(testcolumn)
values (1)
set @i = @i + 1
end
COMMIT

要生成示例数据,您可以使用递归CTE

WITH    q (num) AS
        (
        SELECT  1
        UNION ALL
        SELECT  num + 1
        FROM    q
        WHERE   num < 2000
        )
INSERT
INTO    testdb(testcolumn)
SELECT  1
FROM    q
OPTION (MAXRECURSION 0)

,会更快。

答案 1 :(得分:7)

1)日志刷新提交。每个事务都必须确保在提交返回之前将日志刷新到磁盘。每个INSERT语句都是一个隐式事务。批量提交:

declare @i int
set @i = 0
set nocount on
begin transaction
while @i < 2000
begin
  insert into testdb(testcolumn)
  values (1)
  set @i = @i + 1
  if (@i % 1000 = 0)
  begin
   commit;
   begin transaction;
  end
end
commit

2)慢盘。检查Avg. Disk sec/Transfer性能计数器,查看您的数据和日志磁盘 3)对于许多指数(不太可能在测试表上)。每个指数几乎与插入物的“表格”一样昂贵 4)触发(再次,不太可能)

最终,衡量。如果您不知道从哪里开始,请遵循Troubleshooting Performance Problems in SQL Server 2005等白皮书的指导原则。

答案 2 :(得分:5)

您有足够的工具/技术可以从这类工作量中获得更高的性能。

  1. 如果适当,可以批量加载任何内容。有些事情你不能。需要针对记录运行验证,目标表具有可为空的列...
  2. 考虑将复杂的数据仓库/ ETL操作移动到没有事务日志记录(也称为简单模式)的登台数据库。这将大大提高性能。然后批量/批量处理数据到目标系统。
  3. 批量非批量装入插入操作。提交每n条记录以1,000开头并从中进行性能调整。
  4. 提高磁盘存储的速度。更快的磁盘比更大和更慢的磁盘要好得多。我工作的最后一个db性能调优项目我们从本地磁盘10,000 RPM转移到SAN然后再回到服务器上的固态磁盘进行某些操作。固态绝对是岩石!但是很贵。
  5. 使用强制,适用于Sql Server的性能调整工具来查找不太明显的瓶颈。有时,最佳操作方法可能是根据与表大小相比插入/删除的记录百分比来删除和重建索引;某些操作期间禁用触发器;并修改数据块中记录的稀疏性。

答案 3 :(得分:3)

除了索引之外,如果您的实际场景与您的示例相同,您可以执行基于集合的方法来插入2000条记录,如下所示:

INSERT testdb(testcolumn)
SELECT 1
FROM master..spt_values
WHERE number BETWEEN 1 AND 2000

答案 4 :(得分:1)

插入速度由以下因素驱动:

  1. 日志磁盘的速度。特别是,日志必须单独存在于卷上,这样磁盘搜索不会减慢速度(可能是40倍效果)
  2. 表格及相关索引/键/触发器等的结构
  3. 您的交易规模。较大的事务需要较少的往返日志磁盘往返,并减少相关的开销。
  4. 命令批量的大小。较大批次比许多个别批次更有效。
  5. 如果有任何兴趣,我会在我的书(Ultra-Fast ASP.NET)中详细介绍,包括基准和示例代码。

答案 5 :(得分:0)

拥有聚簇索引(通常是主键)实际上会提高插入速度,因此请确认您拥有其中一个。如果您可以同时拥有所有数据并将其插入表中,则对表运行1000个事务并不是最快的方法(这可以通过使用sql server 2008中的表值参数或2005年的xml参数来实现)。

答案 6 :(得分:0)

我会google到“SQL Server Tuning”......有很多关于这个主题的书。这是一件非常难以解决的事情,因为有许多因素影响速度,从查询语法到分配给服务器的RAM,到分配的RAM(你分配RAM的SQL Server的一部分)的比例,到RAID阵列配置,和许多其他因素。您可以为插入/更新(OLTP)或查询(数据仓库类型的东西)优化数据库服务器。换句话说,不要指望对此有一个简单的答案,即使你的问题看起来很简单。

这就是您拥有数据库服务器管理员的原因。

或者,如果时间对您来说不是很重要,那么您可以尽可能地解决服务器端问题并尽可能优化客户端代码。

我会将准备好的陈述和交易作为开始优化的一种方式。然后看一下索引(如果这是一组经常不会发生的插入,我会考虑删除索引,进行导入,再次创建索引)。