Php 循环中的查询速度越来越慢
我有一个进程,它逐行读取数据提要,解析数据并将其插入MyISAM表。当它第一次启动时,速度非常快,大约每秒1000条记录。随着时间的推移,它变得越来越慢,现在我们大约是每180秒1行 函数的一般语法为: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,
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
。