我在向 MSSQLSRV 2008 R2 中的暂存表中批量插入时遇到问题。
我正在插入约 200,000 行的 CSV,大约需要 5 分钟才能完成。
我尝试同时使用 PDO 和 sqlsrv 驱动程序。他们似乎都表现不佳。
这是让我了解我在做什么的代码(我包括了 SQLSRV 和 PDO 代码):
...
try {
//create structure table record
foreach ($mapped_data as $k => $v) {
$insert .= $k . ",";
$values .= $v . ",";
}
$insert = substr($insert, 0, -1); //remove last ,
$values = substr($values, 0, -1);
$tableName = $table;
if ($stageData) {
$tableName = "stage_$table";
}
if ( $query == "" )
$query = "INSERT INTO $tableName ($insert) VALUES ";
$query .= "($values),";
// Insert in blocks of 1000 lines
if ($line % 1000 == 0) {
$log->logInfo("Executing @ line: $line");
$query = substr($query, 0, -1); //remove last ,
$query .= ";";
// ======================
// = SQLSRV DRIVER CODE =
// ======================
sqlsrv_begin_transaction($sqlsrvConn);
$queryResult = sqlsrv_query($sqlsrvConn,$query);
if ($queryResult) {
sqlsrv_commit($sqlsrvConn);
} else {
sqlsrv_rollback($sqlsrvConn);
}
// ===================
// = PDO DRIVER CODE =
// ===================
$conn->beginTransaction();
$res = $conn->prepare($query);
if($res->execute() === false) {
$errInfo = $res->errorInfo();
if ( $conn->inTransaction() ) {
$conn->rollback();
}
$log->logInfo('Data importing error on line: ' . $line . $errInfo[2]);
$errors[] = 'Data importing error on line: ' . $line . $errInfo[2];
} else {
if ( $conn->inTransaction() ) {
$conn->commit();
$query = "";
$importedRows += ($line - 6) - $importedRows;
}
}
}
}
catch (PDOException $e) {
if ( $conn->inTransaction() ) {
$conn->rollBack();
}
$log->logInfo('PDO Exception: ' . $e->getMessage());
$errors[] = 'PDO Exception: ' . $e->getMessage();
}
$line++;
} // End of while loop through each CSV Line
fclose($handle);
$totalRows = $line - 6;
$importedRows += $totalRows - $importedRows;
// Insert remaing queries afterwards...
...
我一直在互联网上搜索可能的解决方案,但未能找到任何有效的方法。
我找到了 this post这基本上是说将行一起批处理(我已经完成了)。
我发现另一篇帖子说 PDO 设置 connectionpooling=0。我试过了,但没有看到任何性能提升。
还有其他人在使用 SQLSRV 和 PHP 时遇到过这个问题吗?
干杯,
最佳答案
我有一个有点类似的问题。因为我的问题是可用内存不足,所以我的服务器不得不花费额外的时间来处理虚拟内存。如果那不是你的问题,我的回答对你没有用。
您正在使用字符串连接后跟 substr 来删除最后一个逗号。当你使用 substr 时,它会制作另一个字符串副本,这对于长字符串来说是内存密集型的。参见 this question例如,当字符串很长时会发生什么。当我切换到数组连接时,由于内存使用量较低,我的速度大大提高了。但是,如果您没有内存问题,数组连接实际上可能是 slower为你。
我看到的其他一些事情是您只需要收集 $inserts 变量一次,并且您不会在不再需要它们时立即取消设置大变量。我不知道纠正这种事情是否会对你产生明显的影响。以下是您可以尝试的基本更改类型:
if(!isset($insert)) {
$insert = array();
$collect = true;
}
$values = $array();
foreach ($mapped_data as $k => $v) {
if(isset($collect))
$insert[] = $k;
$values[] = $v;
}
unset($collect);
.....
if(!isset($queryend))
$queryend = array();
$queryend[] = "(".implode(",",$values).")";
.....
$query = "INSERT INTO $tableName ("
.implode(",",$insert)
.") VALUES "
.implode(",", $queryend);
unset($queryend); //always unset big things as soon as possible
..... //after $res = $conn->prepare($query);
unset($query);
关于PHP w/MS SQL 在批量插入时速度慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19231473/
我有一个数据对象,其中包含许多用于各种输入的attr_accessor字段。我可以以某种方式定义类,以便所有字段的所有setter都将例如将值设置为空字符串而不是尝试的nil? 最佳答案 这里有一个小模块可以做到这一点:moduleNilToBlankAttrAccessordefnil_to_blank_attr_accessor(attr)attr_readerattrdefine_method"#{attr}="do|value|value=''ifvalue.nil?instance_variable_set"@#{attr
我想使用Ruby检查数千对文件中的每对文件是否包含相同的信息。有人能指出我正确的方向吗? 最佳答案 require'fileutils'FileUtils.compare_file('file1','file2')当且仅当文件file1和file2相同时返回true。 关于ruby-如何批量检查文件内容是否相同,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/33769865/
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭10年前。在我在网上找到的每个基准测试中,Ruby似乎都很慢,比Java慢得多。Ruby的人只是说这无关紧要。您能举个例子说明RubyonRails(以及Ruby本身)的速度真的无关紧要吗?
假设你有这个结构:classHouse请注意,Tv的用户是故意不可访问的。所以你有一个三层嵌套的表单,允许你在一个页面上输入房子、房间和电视。这是Controller的创建方法:defcreate@house=House.new(params[:house])if@house.save#...standardstuffelse#...standardstuffendend问题:您究竟如何为每台电视填充user_id(它应该来自current_user.id)?什么是好的做法?这是我在其中看到的catch22。将user_ids直接填充到params散列中(它们嵌套得很深)保存将失败,因
我有这段代码:date_counter=Time.mktime(2011,01,01,00,00,00,"+05:00")@weeks=Array.new(date_counter..Time.now).step(1.week)do|week|logger.debug"WEEK:"+week.inspect@weeks从技术上讲,代码有效,输出:SatJan0100:00:00-05002011SatJan0800:00:00-05002011SatJan1500:00:00-05002011etc.但是执行时间完全是垃圾!每周计算大约需要四秒钟。我在这段代码中是否遗漏了一些奇怪的低效
我运行的是OSX,对视频转换一无所知。但我有大约200个视频都是mp4格式,无法在Firefox中播放。我需要将它们转换为ogg才能使用html5视频标签。这些文件位于一个文件夹结构中,这使得一次一个地处理一个文件变得困难。我希望bash命令或Ruby命令遍历所有子文件夹并找到所有.mp4并转换它们。我找到了一份关于如何使用Google执行此操作的引用资料:http://athmasagar.wordpress.com/2011/05/12/a-bash-script-to-convert-mp4-files-to-oggogv/#!/bin/bashforfin$(ls*mp4|se
我想知道NokogiriXPath或CSS解析是否可以更快地处理HTML文件。速度有何不同? 最佳答案 Nokogiri没有XPath或CSS解析。它将XML/HTML解析为单个DOM,然后您可以使用CSS或XPath语法进行查询。CSS选择器在要求libxml2执行查询之前在内部转换为XPath。因此(对于完全相同的选择器)XPath版本会快一点点,因为CSS不需要先转换成XPath。但是,您的问题没有通用答案;这取决于您选择的是什么,以及您的XPath是什么样的。很有可能,您不会编写与Nokogiri创建的相同的XPath。例如
我正在使用RubyonRails3.2.2,我想知道在范围方法中是否可以“动态”连接一个表,前提是该表尚未连接。那它,我有:defself.scope_method_name(user)joins(:joining_association_name).where("joining_table_name.user_id=?",user.id)end我想做如下的东西:#Note:thefollowingcodeisjustasampleinordertounderstandwhatImean.defself.scope_method_name(user)iftable_is_joined?
我正在用Ruby编写类似curses的程序,我正在使用stty和ansi转义字符来实现我想要的。当我想获得用户输入时,我的问题就出现了。像许多基于控制台的程序一样,我想从终端底部获取用户输入。因此,我将光标放在屏幕底部并调用Readline.readline(或任何获取用户输入的方法)。像往常一样,它会读取所有内容,直到我按下回车键,并打印一个换行符。由于光标位于终端的最后一行,它会滚动一行,这会弄乱屏幕。我怎样才能避免这种情况?我试图使用stty来停止回显换行符,但我没有成功。也许可以使用stty来阻止终端滚动?当然,我可以编写自己的方法来通过一次读取一个字符(并捕获“返回”)来捕获
在过去的C#和Java工作中,我习惯于这样的声明不是线程安全的:x+=y;但是,在与Ruby并行运行上述代码时,我未能观察到任何线程间的冲突。我读过Rubyautomaticallypreventsmultiplethreadsfromwritingtothesamedataconcurrently.这是真的?因此+=运算符在Ruby中是线程安全的吗? 最佳答案 好吧,这取决于您的实现和很多事情。在MRI中,有一个GVL(GiantVMLock)这样的东西,它控制哪个线程一次实际执行代码。你看,在MRI中,一次只有一个线程可以执行R