你正在做几件错事。首先你必须考虑的是你正在使用的MySQL引擎。
默认的是InnoDB,以前的默认引擎是MyISAM。
我会在假设你使用InnoDB的情况下写出这个答案,你应该使用这个答案的原因很多。 InnoDB在所谓的自动提交模式下运行。这意味着你所做的每个查询都包含在一个事务中。 要翻译成我们凡人能理解的语言 - 你做的每一个查询没有指定BEGIN WORK;
块是一个事务 - ergo,MySQL将等待,直到硬盘确认数据已被写入。
知道硬盘驱动器速度很慢(机械驱动器仍然是最常用的驱动器),这意味着您的插入速度将与硬盘驱动器一样快。通常情况下,机械硬盘驱动器每秒可以执行大约300次输入输出操作,假设您可以每秒执行300次插入 - 是的,您将等待很长时间才能插入100万条记录。
因此,知道事情如何运作 - 您可以使用它们来获得优势。
HDD每笔交易写入的数据量通常会非常小(4KB甚至更少),并且知道今天的HDD可以写入超过100MB /秒 - 这表明我们应该将几个查询包装到单个事务中。
这样MySQL会发送相当多的数据,并等待硬盘确认它写了所有内容,整个世界都很好。
因此,假设您有1M行要填充 - 您将执行1M查询。如果您的事务一次提交1000个查询,则只应执行大约1000次写入操作。
这样一来,你的代码变得东西这样的:
(我不熟悉的mysqli接口,这样的函数名称可能是错的,看到我打字,而无需实际运行的代码 - 的例子可能不起作用请自行承担风险)
function generateRandomData()
{
$db = new mysqli('localhost','XXX','XXX','scores');
if(mysqli_connect_errno()) {
echo 'Failed to connect to database. Please try again later.';
exit;
}
$query = "insert into scoretable values(?,?,?)";
// We prepare ONCE, that's the point of prepared statements
$stmt = $db->prepare($query);
$start = 0;
$top = 1000000;
for($a = $start; $a < $top; $a++)
{
// If this is the very first iteration, start the transaction
if($a == 0)
{
$db->begin_transaction();
}
$id = rand(1,75000);
$score = rand(1,100000);
$time = rand(1367038800 ,1369630800);
$stmt->bind_param("iii",$id,$score,$time);
$stmt->execute();
// Commit on every thousandth query
if(($a % 1000) == 0 && $a != ($top - 1))
{
$db->commit();
$db->begin_transaction();
}
// If this is the very last query, then we just need to commit and end
if($a == ($top - 1))
{
$db->commit();
}
}
}
我宁愿建议完全准备查询然后单次执行它。这将有效地减少时间 –
在这里看到:http://stackoverflow.com/a/3711277/1755720 –
没有预先准备好的声明没有注意到一个区别。我对Web开发很陌生,有一点我还不完全了解,那就是索引,这在我的表中是没有的。这可能会影响速度吗? – rfgordan