PHP在读取具有数千行的文件时提高执行多个查询的性能

时间:2017-10-28 16:28:04

标签: php mysql pdo

我正在尝试构建一个脚本,我需要读取txt文件并使用文件中的行执行某些过程。例如,我需要检查ID是否存在,如果信息已更新,如果是,则更新当前表,如果否,则在另一个临时表上插入一个新行,以便稍后手动检查。

这些文件可能包含超过20,30,000行。

当我刚读取文件并从行中打印一些dummie内容时,它需要40-50ms。但是,当我需要连接到数据库进行所有这些验证时,由于超时,它会在结束前停止。

这就是我到目前为止所做的事情:

$handle = fopen($path, "r") or die("Couldn't get handle");
if ($handle) {
    while (!feof($handle)) {
        $buffer = fgets($handle, 4096);
        $segment = explode('|', $buffer);

        if ( strlen($segment[0]) > 6 ) {
            $param = [':code' => intval($segment[0])];
            $codeObj = Sql::exec("SELECT value FROM product WHERE code = :code", $param);

            if ( !$codeObj ) {
                $param = [
                    ':code' => $segment[0],
                    ':name' => $segment[1],
                    ':value' => $segment[2],
                ];
                Sql::exec("INSERT INTO product_tmp (code, name, value) VALUES (:code, :name, :value)", $param);
            } else {
                if ( $codeObj->value !== $segment[2] ) {
                    $param = [
                        ':code' => $segment[0],
                        ':value' => $segment[2],
                    ];
                    Sql::exec("UPDATE product SET value = :value WHERE code = :code", $param);
                }
            }
        }
    }

    fclose($handle);
}

这是我的Sql类,用于连接PDO并执行查询:

public static function exec($sql, $param = null) {
    try {
        $conn = new PDO('mysql:charset=utf8mb4;host= '....'); // I've just deleted the information to connect to the database (password, user, etc.)
        $q = $conn->prepare($sql);

        if ( isset($param) ) {
            foreach ($param as $key => $value) {
                $$key = $value;
                $q->bindParam($key, $$key);
            }
        }

        $q->execute();
        $response = $q->fetchAll();

        if ( count($response) ) return $response;
        return false;
    } catch(PDOException $e) {
        return 'ERROR: ' . $e->getMessage();
    }
}

如您所见,我通过Sql::exec()执行的每个查询都在打开一个新连接。我不知道这是否可能是导致此过程延迟的原因,因为当我不进行任何Sql查询时,该脚本在ms内运行。

或者代码的其他部分可能导致此问题?

1 个答案:

答案 0 :(得分:0)

首先,让你的功能像这样, 避免多重连接,也摆脱无用的代码。

public static function getPDO() {
    if (!static::$conn) {
        static::$conn = new PDO('mysql:charset=utf8mb4;host= ....'); 
    }
    return static::$conn;
}
public static function exec($sql, $param = null) {
    $q = static::getPDO()->prepare($sql);
    $q->execute($param);
    return $q;
}

然后为code字段

创建唯一索引

然后使用单个INSERT ... ON DUPLICATE KEY UPDATE查询而不是您的thrree查询

您可能还想在事务中包装插入内容,它可能会最多加快插入次数。

相关问题