在寻找从 Java 获取数据到 SQL Server 的最快方法的过程中,我注意到我能想到的最快的 Java 方法仍然比使用 BULK INSERT 慢 12 倍。
我的数据是从 Java 中生成的,而 BULK INSERT 只支持从文本文件中读取数据,因此除非我将数据输出到临时文本文件,否则不能使用 BULK INSERT。反过来,这当然会对性能造成巨大影响。
从 Java 插入时,插入速度约为每秒 2500 行。 甚至 当我在 for 循环之后 和 executeBatch 之前测量时间时。因此,在内存中“创建”数据不是瓶颈。
使用 BATCH INSERT 插入时,插入速度约为每秒 30000 行。
这两个测试都是在服务器上完成的。所以网络也不是瓶颈。关于为什么 BATCH INSERT 更快的任何线索?而且,是否可以从 Java 中获得相同的性能?
这只是一个需要加载一次的大数据集。因此,可以暂时禁用任何类型的日志记录(已经尝试过简单的日志记录)、禁用索引(表没有)、锁定等等......
到目前为止我的测试设置
数据库:
CREATE TABLE TestTable
( Col1 varchar(50)
, Col2 int);
Java:
// This seems to be essential to get good speeds, otherwise batching is not used.
conn.setAutoCommit(false);
PreparedStatement prepStmt = conn.prepareStatement("INSERT INTO TestTable (Col1, Col2) VALUES (?, ?)");
for (int i = 1; i <= 10000; i++) {
prepStmt.setString(1,"X");
prepStmt.setInt(2,100);
prepStmt.addBatch();
}
prepStmt.executeBatch();
conn.commit();
批量插入:
// A text file containing "X 100" over and over again... so the same data as generated in JAVA
bulk insert TestTable FROM 'c:\test\test.txt';
最佳答案
虽然 BULK INSERT 是执行批量插入的最快方法,但 SQL Server 通过 native 驱动程序和 ODBC 支持远程(客户端驱动的)批量插入操作。 From version 4.2 onwards of the JDBC driver , 此功能通过 SQLServerBulkCopy 公开类,它不直接从文件中读取,但支持从 RowSet、ResultSet 或 ISQLServerBulkRecord 的自定义实现中读取生成的数据。此功能等效于 .NET SqlBulkCopy 类,具有大致相同的接口(interface),并且应该是执行批量操作的最快方式,而不是基于服务器的 BULK INSERT。
编辑:OP 示例
您可以在下面找到一个示例用例,该用例可用于测试 SQLServerBulkCSVFileRecord 的性能,该方法类似于 SQLServerBulkCopy,只是它从文本文件中读取。在我的测试用例中,test.txt 包含一百万行带有“X tab
100"
CREATE TABLE TestTable (Col1 varchar(50), Col2 int);
该表不应启用任何索引。
在 JAVA 中
// Make sure to use version 4.2, as SQLServerBulkCSVFileRecord is not included in version 4.1
import com.microsoft.sqlserver.jdbc.*;
long startTime = System.currentTimeMillis();
SQLServerBulkCSVFileRecord fileRecord = null;
fileRecord = new SQLServerBulkCSVFileRecord("C:\\temp\\test.txt", true);
fileRecord.addColumnMetadata(1, null, java.sql.Types.NVARCHAR, 50, 0);
fileRecord.addColumnMetadata(2, null, java.sql.Types.INTEGER, 0, 0);
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
Connection destinationConnection = DriverManager.getConnection("jdbc:sqlserver://Server\\\\Instance:1433", "user", "pass");
SQLServerBulkCopyOptions copyOptions = new SQLServerBulkCopyOptions();
// Depending on the size of the data being uploaded, and the amount of RAM, an optimum can be found here. Play around with this to improve performance.
copyOptions.setBatchSize(300000);
// This is crucial to get good performance
copyOptions.setTableLock(true);
SQLServerBulkCopy bulkCopy = new SQLServerBulkCopy(destinationConnection);
bulkCopy.setBulkCopyOptions(copyOptions);
bulkCopy.setDestinationTableName("TestTable");
bulkCopy.writeToServer(fileRecord);
long endTime = System.currentTimeMillis();
long totalTime = endTime - startTime;
System.out.println(totalTime + "ms");
使用这个示例,我能够获得高达每秒 30000 行的插入速度。
关于java - 从 Java 插入到 SQL Server 时,我可以获得类似 "BULK INSERT"的速度吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40471004/
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou
我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-
使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta
查看Ruby的CSV库的文档,我非常确定这是可能且简单的。我只需要使用Ruby删除CSV文件的前三列,但我没有成功运行它。 最佳答案 csv_table=CSV.read(file_path_in,:headers=>true)csv_table.delete("header_name")csv_table.to_csv#=>ThenewCSVinstringformat检查CSV::Table文档:http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV/Table.html
为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar
我发现ActiveRecord::Base.transaction在复杂方法中非常有效。我想知道是否可以在如下事务中从AWSS3上传/删除文件:S3Object.transactiondo#writeintofiles#raiseanexceptionend引发异常后,每个操作都应在S3上回滚。S3Object这可能吗?? 最佳答案 虽然S3API具有批量删除功能,但它不支持事务,因为每个删除操作都可以独立于其他操作成功/失败。该API不提供任何批量上传功能(通过PUT或POST),因此每个上传操作都是通过一个独立的API调用完成的
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test
我使用的是Firefox版本36.0.1和Selenium-Webdrivergem版本2.45.0。我能够创建Firefox实例,但无法使用脚本继续进行进一步的操作无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055)错误。有人能帮帮我吗? 最佳答案 我遇到了同样的问题。降级到firefoxv33后一切正常。您可以找到旧版本here 关于ruby-无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055),我们在StackOverflow上找到一个类