我有一个逐行读取数据源的进程,解析并将数据插入到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' :
...
}
}
}
正在解析的当前文件有几百万条记录。服务器似乎没有丢失内存空间。有人知道导致这个过程变慢的原因吗?
答案 0 :(得分:6)
这可能与必须经常写入索引有关。您已经在使用MyISAM,这将是我的第一个建议。
一些建议
答案 1 :(得分:3)
您可能在此表上至少有一个索引。因此每行都会插入越来越大的索引中。在开始加载之前,请执行
ALTER TABLE表DISABLE KEYS
完成后
ALTER TABLE表启用键
重新启用密钥可能需要一段时间。
加载时请勿尝试使用该表。此外,INSERT DELAYED可能有所帮助。但是,如果您在一个安静的数据库服务器上执行此表加载,可能不会。
答案 2 :(得分:1)
我认为你应该在事务中运行查询(它有加速),最好使用PDO因为它更安全。在PDO中准备好的声明可能会更快,但至少更安全,因为它们对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);
P.S:我还想指出InnoDB可能会更好。