Вы делаете несколько вещей неправильно. Первое, что вы должны учитывать, - это то, что вы используете MySQL.
По умолчанию используется InnoDB, ранее по умолчанию использовался MyISAM.
Я напишу этот ответ в предположении, что вы используете InnoDB, который вы должны использовать по множеству причин. InnoDB работает во встроенном режиме автосохранения. Это означает, что каждый сделанный вами запрос заключен в транзакцию. Чтобы перевести это на язык, который мы можем понять простым смертным - каждый запрос, который вы делаете без с указанием BEGIN WORK;
блок - транзакция - ergo, MySQL будет ждать, пока жесткий диск не подтвердит, что данные были написаны.
Зная, что жесткие диски медленные (механические все еще наиболее широко используются), это означает, что ваши вставки будут такими же быстрыми, как на жестком диске. Обычно механические жесткие диски могут выполнять около 300 операций ввода вывода в секунду, считая, что вы можете делать 300 вставок в секунду - да, вы будете ждать совсем немного, чтобы вставить 1 миллион записей.
Итак, зная, как все работает - вы можете использовать их в своих интересах.
Объем данных, которые HDD записывает за транзакцию, будет в целом очень маленьким (4 КБ или даже меньше), и знание современных жестких дисков может записывать более 100 МБ/с - это означает, что мы должны обернуть несколько запросов в одну транзакцию ,
Таким образом, MySQL отправит довольно много данных и дождитесь, пока HDD подтвердит, что он написал все и что весь мир в порядке и денди.
Итак, если у вас есть 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 –
не замечая разницы без подготовленных операторов. Я немного новый для веб-разработки, и одна вещь, которую я до сих пор не совсем понимаю, - это индексы, которых у меня нет в моей таблице. Может ли это повлиять на скорость? – rfgordan