php mysql多线程处理数据_关于php:如何使用多线程在mysql数据库中上传csv文件?...

本文探讨了如何使用PHP处理大量CSV数据并将其高效上传到MySQL数据库。针对单线程上传时间过长的问题,提出了通过拆分CSV文件并使用多个子任务并行处理的方案,详细介绍了实现这一目标的PHP代码示例,包括主线程和子线程的处理逻辑。此外,还讨论了优化查询性能和避免SQL注入的重要性。
摘要由CSDN通过智能技术生成

我有一个csv文件,包含数百万个电子邮件地址,我想用PHP快速上传到mysql数据库。

现在我正在使用单线程程序,上传时间太长。

//get the csv file

$file = $_FILES['csv']['tmp_name'];

$handle = fopen($file,"r");

//loop through the csv file and insert into database

do {

if ($data[0]) {

$expression ="/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$/";

if (preg_match($expression, $data[0])) {

$query=mysql_query("SELECT * FROM `postfix`.`recipient_access` where recipient='".$data[0]."'");

mysql_query("SET NAMES utf8");

$fetch=mysql_fetch_array($query);

if($fetch['recipient']!=$data[0]){

$query=mysql_query("INSERT INTO `postfix`.`recipient_access`(`recipient`, `note`) VALUES('".addslashes($data[0])."','".$_POST['note']."')");

}

}

}

} while ($data = fgetcsv($handle,1000,",","'"));

你是否需要经常这样做,就像每天一样?如果没有,我会把事情保留原样并等待。对于任何线程解决方案,您几乎肯定必须在PHP之外。确保您的表格已正确编入索引,因此您的选择以最佳速度运行。你只需要SET NAMES一次,把它从循环中取出来。

为什么用PHP而不是MySQL处理它?

它的工作,但我需要多线程程序上传文件十次或更多fater使用核心PHP

好吧,我需要一百万美元。但是我不太可能很快得到它们。我很确定这同样适用于这个要求:)

我有成千上万的文件,它会日复一日地增加,它不适合通过MySQL。

我有另一个想法,在上传文件时打破我的csv文件很多部分。此文件将被许多循环上传。但是我怎样才能在PHP中分割或破坏许多部分的文件

您的一个文件中有数千行,或者每天上传数千个文件?也许尝试减少这些文件的数据?如果这些文件包含图像数据中的图像,可能使用图像URL而不是?

Umesh,这个过程是高度可优化的,但涉及结构修改。

首先,我不能给人足够的压力;修复你的缩进 - 它将使每个人的生活更轻松。

其次,答案很大程度上取决于您遇到的实际瓶颈:

正则表达式非常慢,特别是当它们处于循环中时。

数据库往往适用于WRITES或READS,但不适用于:尝试预先减少查询量。

按理说,循环中的PHP代码越少,它的工作速度就越快。考虑减少条件(例如)。

为了记录,您的代码对于mysql注入是不安全的:在手[*]之前过滤$ _POST

[*]说到这一点,访问一个变量比一个数组的索引更快,比如$ _POST。

您可以通过让主程序将巨大的CSV文件拆分为较小的CSV文件并将每个文件运行到不同的进程来模拟多线程。

的common.php

class FileLineFinder {

protected $handle, $length, $curpos;

public function __construct($file){

$handle = fopen($file, 'r');

$length = strlen(PHP_EOL);

}

public function next_line(){

while(!feof($this->handle)){

$b = fread($this->handle, $this->length);

$this->curpos += $this->length;

if ($b == PHP_EOL) return $this->curpos;

}

return false;

}

public function skip_lines($count){

for($i = 0; $i < $count; $i++)

$this->next_line();

}

public function __destruct(){

fclose($this->handle);

}

}

function exec_async($cmd, $outfile, $pidfile){

exec(sprintf("%s > %s 2>&1 & echo $! >> %s", $cmd, $outfile, $pidfile));

}

main.php

require('common.php');

$maxlines = 200;      // maximum lines subtask will be processing at a time

$note = $_POST['note'];

$file = $_FILES['csv']['tmp_name'];

$outdir = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'out' . DIRECTORY_SEPARATOR;

//make sure our output directory exists

if(!is_dir($outdir))

if(!mkdir($outdir, 0755, true))

die('Cannot create output directory: '.$outdir);

// run a task for each chunk of lines in the csv file

$i = 0; $pos = 0;

$l = new FileLineFinder($file);

do {

$i++;

exec_async(

'php -f sub.php -- '.$pos.' '.$maxlines.' '.escapeshellarg($file).' '.escapeshellarg($note),

$outdir.'proc'.$i.'.log',

$outdir.'proc'.$i.'.pid'

);

$l->skip_lines($maxlines);

} while($pos = $l->next_line());

// wait for each task to finish

do {

$tasks = count(glob($outdir.'proc*.pid'));

echo 'Remaining Tasks: '.$tasks.PHP_EOL;

} while ($tasks > 0);

echo 'Finished!'.PHP_EOL;

sub.php

require('common.php');

$start = (int)$argv[1];

$count = (int)$argv[2];

$file = $argv[3];

$note = mysql_real_escape_string($argv[4]);

$lines = 0;

$handle = fopen($file, 'r');

fseek($handle, $start, SEEK_SET);

$expression ="/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$/";

mysql_query('SET NAMES utf8');

//loop through the csv file and insert into database

do {

$lines++;

if ($data[0]) {

if (preg_match($expression, $data[0])) {

$query = mysql_query('SELECT * FROM `postfix`.`recipient_access` where recipient="'.$data[0].'"');

$fetch = mysql_fetch_array($query);

if($fetch['recipient'] != $data[0]){

$query = mysql_query('INSERT INTO `postfix`.`recipient_access`(`recipient`, `note`) VALUES("'.$data[0].'","'.$note.'")');

}

}

}

} while (($data = fgetcsv($handle, 1000, ',', '\'')) && ($lines < $count));

积分

https://stackoverflow.com/a/2162528/314056

https://stackoverflow.com/a/45966/314056

将整个循环放在SQL事务中。这将使事情加快一个数量级。

一般建议:加速任何程序的关键是知道哪个部分占用大部分时间。

然后弄清楚如何减少它。有时您会对实际结果感到非常惊讶。

顺便说一句,我不认为多线程会解决你的问题。

最紧迫的事情是确保您的数据库已正确编入索引,以便您为每一行执行的查询查询尽可能快。

除此之外,你可以做的事情并不多。对于多线程解决方案,您必须在PHP之外。

您也可以在mySQL中导入CSV文件,然后使用PHP脚本清除多余的数据 - 这可能是最快的方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值