Php 循环中的查询速度越来越慢

Php 循环中的查询速度越来越慢,php,mysql,performance,Php,Mysql,Performance,我有一个进程,它逐行读取数据提要,解析数据并将其插入MyISAM表。当它第一次启动时,速度非常快,大约每秒1000条记录。随着时间的推移,它变得越来越慢,现在我们大约是每180秒1行 函数的一般语法为: function parse($file) { $handle = fopen($file, 'r'); while (!feof($handle)) { $line = fgets($fileHandle, 1000); switch (substr($line, 0,

我有一个进程,它逐行读取数据提要,解析数据并将其插入MyISAM表。当它第一次启动时,速度非常快,大约每秒1000条记录。随着时间的推移,它变得越来越慢,现在我们大约是每180秒1行

函数的一般语法为:

function parse($file) {
  $handle = fopen($file, 'r');
  while (!feof($handle)) {
    $line = fgets($fileHandle, 1000);
    switch (substr($line, 0, 2)) { //gets record type
      case '01' :
        //parse the record
        //escapes some strings with mysql_real_escape_string()
        mysql_query('INSERT INTO table VALUES ($a, $b, $c...');
      case '02' :
        ...
    }
  }
}

正在分析的当前文件有几百万条记录。服务器似乎没有丢失内存空间。有人知道是什么原因导致流程变慢了吗?

我认为您应该在事务中运行查询(它得到了加速),最好使用,因为这样更安全。PDO中的prepared语句可能会更快,但至少更安全,因为它们不受SQL注入的影响。那样会快得多。我为您准备了一个带有标签的示例:

<?php

$array = array(
    "ActionScript",
    "AppleScript",
    "Asp",
    "BASIC",
    "C",
    "C++",
    "Clojure",
    "COBOL",
    "ColdFusion",
    "Erlang",
    "Fortran",
    "Groovy",
    "Haskell",
    "Java",
    "JavaScript",
    "Lisp",
    "Perl",
    "PHP",
    "Python",
    "Ruby",
    "Scala",
    "Scheme"
);

function createTable($db) {
    $db->exec("CREATE TABLE IF NOT EXISTS tags (id INTEGER PRIMARY KEY, tag TEXT NOT NULL UNIQUE)");
}

function insertData($db, $array) {
    $db->beginTransaction();

    foreach($array as $elm) {
        try {
            $placeholder = array($elm);
            $stmt = $db->prepare("INSERT INTO tags (tag) VALUES (?)");
            $stmt->execute($placeholder);
        } catch(PDOException $e) {
            /*** roll back the transaction if we fail ***/
            $db->rollback();
            /*** echo the sql statement and error message ***/
            echo $sql . '<br />' . $e->getMessage();
        }
    }

    $db->commit();
}

$db = new PDO('sqlite:database/tags.sqlite3');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
//
createTable($db);
insertData($db, $array);

这可能与必须如此频繁地写入索引有关。您已经在使用MyISAM,这将是我的第一个建议

一些建议

  • 每100行批插入一次
  • 使用INSERT DELAYED允许MySQL允许INSERT快速完成排队,并且MySQL将在资源更允许时插入记录
  • 让您的脚本创建一个SQL转储/分隔文件,您可以使用文件导入函数加载该文件,查看哪个比批插入快得多

  • 此表上可能至少有一个索引。因此,每一行都被插入到一个越来越大的索引中。在开始加载之前,请执行以下操作:

    ALTER TABLE表禁用键

    等你做完了再做

    ALTER TABLE表启用键

    重新启用这些键可能需要一段时间


    加载时不要试图使用该表。此外,插入延迟可能会有所帮助。但如果您是在一个安静的数据库服务器上执行此表加载,则可能不会。

    表上有索引吗?索引更新可能是罪魁祸首。还有,你多久提交一次?你在“表”上有索引吗?@bensiu&@Jim Garrison-为什么你需要为INSERT建立索引?也许你应该使用你的模式发布帖子?@FeRtoll-你不需要为INSERT建立索引,但是,如果在执行插入时表上有索引,则必须重写索引以包含最近插入的记录-这会减慢插入过程MyISAM完全忽略事务。数据来自内部提要,我不担心SQL注入。我不认为我使用的Php版本支持PDO,但它可以为我的案例添加弹药进行升级。它做了MySQL还没有做的优化吗?哇,你以前使用的是PHP版本吗?你应该告诉你的管理员你需要PHP5.3,因为即使不做任何事情,你也应该得到一个。准备好的语句是预编译的,因此您应该/可以看到速度的提高。@PMV我认为这是一件非常明智的事情:P.
    mysql\uquot.
    接口在最新版本中已被删除!谢谢,我要试试这些。只有一个索引,即自动递增列上的主键。@ParrisVarney-您提供的
    插入
    与具有
    自动递增
    不兼容!请提供
    SHOW CREATE TABLE