Closed. This question needs to be more focused。它目前不接受答案。
想改进这个问题吗?更新问题,使其只关注一个问题editing this post。
5年前关闭。
关于加快插入SQL数据库的速度,有很多问题,例如this、this、this、this和(我最喜欢的)this。许多问题伪装成依赖语言,但问题通常会归结为:
什么样的通用技术可以加快从我的[特定语言]程序插入到我的[特定数据库管理系统]SQL数据库的速度?
基线:一次插入一个
在Ruby On Rails中,您可以执行以下操作:
基本上转化为123000个单独的SQL调用:
加速1:包在事务中
这几乎是相同的,但在单个SQL事务中包装内部循环:
加速2:批量插入版本A
这个函数将原始数组分成500个批(以避免SQLite和潜在的字符串缓冲区大小的限制),每个事务的格式如下:
加速3:批量插入版本B
有些dbms不支持大容量插入版本A的语法(特别是老版本的SQLite)。以下表单在功能上是相同的,并受许多数据库的支持(尽管不严格遵循SQL-92):
加速4:DBM特定方法
正如https://stackoverflow.com/users/20860/bill-karwin所指出的,人们可以
利用特定于供应商的批量加载命令,例如
为MySQL加载数据填充、为PostgreSQL复制或为
甲骨文等,每个品牌都有自己的命令或工具,所以没有
供应商中立的方法,但这些方法通常有
数量级更好的性能,所以它们不应该
被忽视了。
虽然这些不是一般的技术,但在特定情况下它们会很有用。在下面的测试中,我们没有对这些进行基准测试。
相对加速
我们在MySQL、PostgreSQL和SQLite中测试了上述各种技术。下面的数字显示了各种方法相对于基线情况的速度。第一个数字是相对用户+系统时间,括号中的数字是相对运行时间。
(注意:我选择不显示绝对时间,因为这不是关于哪个数据库最快的讨论——变量太多,无法对此做出合理的声明。如果轻推,我将把这两个代码都发布到github上,您可以运行自己的测试并得出自己的结论。)
MySQL数据库
在事务中包装:1.2x(1.4x)
批量插入版本A:24.3x(19.0x)
批量插入版本B:24.3x(17.1x)
PostgreSQL公司
在事务中包装:1.2x(1.6x)
批量插入版本A:27.2x(16.7x)
批量插入版本B:27.2x(13.9x)
数据库
在事务中包装:1.6x(2.4x)
批量插入版本A:25.8x(24.7x)
批量插入版本B:24.1x(34.1x)
测试说明
想改进这个问题吗?更新问题,使其只关注一个问题editing this post。
5年前关闭。
关于加快插入SQL数据库的速度,有很多问题,例如this、this、this、this和(我最喜欢的)this。许多问题伪装成依赖语言,但问题通常会归结为:
什么样的通用技术可以加快从我的[特定语言]程序插入到我的[特定数据库管理系统]SQL数据库的速度?
最佳答案
插入过程中最大的效率低下来自两个来源:单独的数据事务需要时间,并且您的语言和数据库之间的ORM适配器并不总是特别有效。
这个答案使用Ruby On Rails作为其示例语言,但是这里显示的技术几乎适用于任何具有底层数据库接口的高级语言。
结论(TL;DR)
通过下面列出的任何一种批量插入方法一次插入500条记录,可以使速度提高20倍以上。通过调整,速度可能会更高。
测试
让我们从内存中123001条记录的数组开始。(这些数据来自[多伦多市交通数据集]的“trips.txt”文件。1)
dataset = Utilities.load_csv(Rails.root.join("datasets", "trips.txt")
基线:一次插入一个
在Ruby On Rails中,您可以执行以下操作:
dataset.each {|record| Trip.create!(record) }
基本上转化为123000个单独的SQL调用:
INSERT INTO "trips" (<column_names>) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) [<column name/value pairs>]
(123000 more times...)
加速1:包在事务中
这几乎是相同的,但在单个SQL事务中包装内部循环:
begin transaction
INSERT INTO "trips" (<column_names>) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) [<column name/value pairs>]
(123000 more times...)
commit transaction
加速2:批量插入版本A
这个函数将原始数组分成500个批(以避免SQLite和潜在的字符串缓冲区大小的限制),每个事务的格式如下:
INSERT INTO trips (comma_separated_column_names) VALUES
(comma_separated_values_for_row_1),
(comma_separated_values_for_row_2),
...
(comma_separated_values_for_row_500);
... repeated 246 times
加速3:批量插入版本B
有些dbms不支持大容量插入版本A的语法(特别是老版本的SQLite)。以下表单在功能上是相同的,并受许多数据库的支持(尽管不严格遵循SQL-92):
INSERT INTO trips (comma_separated_column_names)
SELECT comma_separated_values_for_row_1
UNION ALL SELECT comma_separated_values_for_row_2
...
UNION ALL SELECT comma_separated_values_for_row_500
...repeated 246 times
加速4:DBM特定方法
正如https://stackoverflow.com/users/20860/bill-karwin所指出的,人们可以
利用特定于供应商的批量加载命令,例如
为MySQL加载数据填充、为PostgreSQL复制或为
甲骨文等,每个品牌都有自己的命令或工具,所以没有
供应商中立的方法,但这些方法通常有
数量级更好的性能,所以它们不应该
被忽视了。
虽然这些不是一般的技术,但在特定情况下它们会很有用。在下面的测试中,我们没有对这些进行基准测试。
相对加速
我们在MySQL、PostgreSQL和SQLite中测试了上述各种技术。下面的数字显示了各种方法相对于基线情况的速度。第一个数字是相对用户+系统时间,括号中的数字是相对运行时间。
(注意:我选择不显示绝对时间,因为这不是关于哪个数据库最快的讨论——变量太多,无法对此做出合理的声明。如果轻推,我将把这两个代码都发布到github上,您可以运行自己的测试并得出自己的结论。)
MySQL数据库
在事务中包装:1.2x(1.4x)
批量插入版本A:24.3x(19.0x)
批量插入版本B:24.3x(17.1x)
PostgreSQL公司
在事务中包装:1.2x(1.6x)
批量插入版本A:27.2x(16.7x)
批量插入版本B:27.2x(13.9x)
数据库
在事务中包装:1.6x(2.4x)
批量插入版本A:25.8x(24.7x)
批量插入版本B:24.1x(34.1x)
测试说明
Processing environment: 2.66 GHz Intel Core i7, 8GB 1067 MHz DDR3
Operating System: OS X v 10.9.5
Ruby version: 2.0.0 (64 bit)
Rails version: 4.0.2
MySQL: Server version: 5.1.49
PostgreSQL: psql (9.3.1, server 8.3.14)
SQLite: SQLite version 3.7.12 2012-04-03 19:43:07