SQL Server/MySQL/Access - 加速以低效方式插入许多行

Mic*_*yor 5 mysql sql-server ms-access

建立

我必须在SQL Server 2000/2005,MySQL或Access中插入几百万行.不幸的是,我没有一种简单的方法来使用批量插入或BCP或普通人类会采用的任何其他方式.插入将发生在一个特定的数据库上,但该代码需要与数据库无关 - 因此我无法进行批量复制,SELECT INTO或BCP.但是,我可以在插入之前和之后运行特定查询,具体取决于我要导入的数据库.

例如.

If IsSqlServer() Then
    DisableTransactionLogging();
ElseIf IsMySQL() Then
    DisableMySQLIndices();
End If

... do inserts ...

If IsSqlServer() Then
    EnableTransactionLogging();
ElseIf IsMySQL() Then
    EnableMySQLIndices();
End If
Run Code Online (Sandbox Code Playgroud)

我可以对SQL Server做些有趣的事情来加速这些插入吗?

例如,是否有一个命令可以告诉SQL Server,"嘿,不要在事务日志中记录这些事务".

或许我可以说,"嘿,我有一百万行进来,所以在我完成之前不要更新你的索引".

ALTER INDEX [IX_TableIndex] ON Table DISABLE
     ... inserts
ALTER INDEX [IX_TableIndex] ON Table REBUILD
Run Code Online (Sandbox Code Playgroud)

(注意:上面的索引禁用仅适用于2005,而不是2000.如果你知道在2000年这样做的方法,可以使用奖励积分).

MySQL和Access怎么样?

Cow*_*wan 4

这里会降低性能的最大因素是(听起来)您正在针对数据库执行一百万个不同的 INSERT。每个 INSERT 都被视为单个操作。如果您可以将其作为单个操作来完成,那么您几乎肯定会获得巨大的性能提升。

MySQL 和 SQL Server 都支持不带表名的常量表达式的“选择”,因此这应该作为一条语句运行:

INSERT INTO MyTable(ID, name)
SELECT 1, 'Fred'
UNION ALL SELECT 2, 'Wilma'
UNION ALL SELECT 3, 'Barney'
UNION ALL SELECT 4, 'Betty'
Run Code Online (Sandbox Code Playgroud)

我不清楚 Access 是否支持该功能,因为 Access 不可用。然而,据我所知,Access 确实支持 SELECT 中的常量,并且您可以将上述内容强制转换为 ANSI SQL-92(所有 3 个引擎都应该支持它;它与您一样接近“与数据库无关”)只需添加即可得到)

FROM OneRowTable
Run Code Online (Sandbox Code Playgroud)

到每个单独 SELECT 的末尾,其中“OneRowTable”是仅包含一行虚拟数据的表。

这应该可以让您在远少于一百万个 INSERT 语句中插入一百万行数据——并且索引重新整理之类的事情将完成一次,而不是一百万次。此后您对其他优化的需求可能会少得多。