使用PHP执行大型SQL查询的最有效方法?

时间:2019-06-24 08:36:50

标签: php sql csv timeout large-data

每隔三个月,我需要上传一个包含约40万种产品的CSV文件,并将其插入MySQL数据库。我觉得我的方法不太有效,并希望提出一些建议。

目前,我像这样解析CSV文件:

public function parse_csv_to_array() {

    // Initialize empty array 
    $array = $fields = array(); 

    $interval = 0;

    // File Handle
    $handle = @fopen($this->csvFile, "r");

    if ($handle) {

        while (($row = fgetcsv($handle, 4096)) !== false) {

            if (empty($fields)) {
                $fields = $row;
                continue;
            }

            foreach ($row as $k=>$value) {
                $array[$interval][$fields[$k]] = $value;
            }

            $interval++;
        }

        if (!feof($handle)) {
            echo "Error: unexpected fgets() fail\n";
        }

        fclose($handle);
    }

    return $array;
}

然后,我简单地遍历数组,以插入新记录或替换现有记录(如果已存在)。这意味着我要执行至少120万个SQL查询,以首先检查记录是否存在,然后将记录插入/替换到数据库中。

当前,这是作为HTML5表单上传完成的,并且在用户单击提交后在用户浏览器中执行。整个过程最多可能需要30分钟,我认为这还不错,但是我不得不将PHP脚本的超时设置为无限制,以允许脚本运行。我觉得这不是非常有效,并且会大大增加服务器的负载。我想知道是否有分割数组并将记录上载到分区中的方法,还是应该使用CRON这样的调度程序。仅在一个脚本中执行120万个SQL查询的想法让人感到肮脏,因此必须有一种更好的方法。任何建议都将受到欢迎。

2 个答案:

答案 0 :(得分:0)

您可以执行一次查询以取回所有记录,将记录存储在数组中,将csv中的数据与数组中的值进行比较,并在必要时进行更新。您还可以创建仅包含需要更新的值的数组,然后进行批量插入。

在这种方法中,您对数据库的请求不多,因此,它的资源消耗应较少。

答案 1 :(得分:0)

我认为使用块和cron将是最好的解决方案。每隔几分钟运行一次cron,以查找新数据并将其上载到数据库(如果有的话)。然后它可以在后台运行。

要加快脚本本身的速度,您还可以对条目和diff进行分块并批量插入。然后,您不必做太多的sql语句。