Ich habe eine Aufgabe zu üben. Generiere 5 Millionen Datensätze: string (15), string (15), int (min: 1 max: 99) und speichere sie in einer Datenbank postgresql. Meine erste Version des Skripts war die geschätzte Zeit für 5 Millionen: 16120 Sekunden.Generieren Sie 5 Millionen Datensätze und fügen Sie sie in fünf Sekunden in die Datenbank ein
EDIT (12. Dezember 15 um 11:50): Nach mehreren Optimierungen derzeit: 80 Sekunden.
Was muss ich ändern, um das gewünschte Ergebnis zu erzielen?
Im Folgenden präsentiere ich die am meisten optimierte Version des Codes.
// In Source Code -> function insertDataFive
$countRecords = 5000000;
for ($i = 0; $i < ($countRecords/100000); $i++) // $i < 50
{
echo "Loop one \$i: " . $i . "\n";
try
{
echo "Memory used (before) real: " . (memory_get_peak_usage(true)/1024/1024) . " MiB\n";
$sql = "INSERT INTO users
(first_name, last_name, user_age)
VALUES ('" . randomString(15) . "','" . randomString(15) . "'," . randomAge() . ")";
for ($j = 1; $j < 100000; $j++)
{
$sql .= ",('" . randomString(15) . "','" . randomString(15) . "'," . randomAge() . ")";
}
$dbh->exec($sql);
echo "Memory used (after) real: " . (memory_get_peak_usage(true)/1024/1024) . " MiB\n\n";
unset($sql);
} catch (PDOException $e)
{
echo 'PDO error: ' . $e->getMessage();
}
}
Vielleicht verwende ich Cloud etwas anderes als INSERT?
EDIT: Problem gelöst! 2016 Dez 19script relase 1.0 source
WICHTIG! bevor ausgeführt, sobald dieses Skript exec in cmd unten Befehl
mkdir/tmp/ram
mount -t tmpfs -o size = 512m tmpfs/tmp/ram
Daten erzeugen:
function createDataFile($task, $rows = 1250000)
{
try
{
global $fileName, $fileExtension, $timeFileCreate;
$startTime = microtime(true);
$fileCSV = $fileName . $task . $fileExtension;
$fileHandler = fopen('/tmp/ram/' . $fileCSV, 'w');
if ($fileHandler != false)
{
if (DEBUG)
{
echo "Memory used (before) fwrite: " . getMemoryUsage() . " MiB\n";
}
for ($i = ($task - 1) * $rows; $i < $task * $rows; $i++)
{
fwrite($fileHandler, (($i + 1 . ","
. generateRangomString(15) . ","
. generateRangomString(15) . ","
. generateRangomAge()) . "\n"));
}
fclose($fileHandler);
if (DEBUG)
{
echo "Memory used (after) fwrite: " . getMemoryUsage() . " MiB\n";
}
}
else
{
echo "File open error";
}
$timeFileCreate += (microtime(true) - $startTime);
}
catch (Exception $ex)
{
echo "File Error: " . $ex->getMessage();
}
}
Zeilen einfügen:
function insertSingleDataFile($dbh, $task)
{
global $fileName, $fileExtension, $timeSqlBulk;
$startTime = microtime(true);
$fileCSV = $fileName . $task . $fileExtension;
$sqlBulk = "COPY users (user_id, first_name, last_name, user_age)
FROM '/tmp/ram/$fileCSV'
DELIMITER ','";
try
{
$dbh->query($sqlBulk);
}
catch (PDOException $e)
{
echo 'PDO error: ' . $e->getMessage() . "\n\n";
}
$timeSqlBulk += (microtime(true) - $startTime);
}
Laden Daten infile und Hinzufügen von Indizes nach Inserts sind die Punkte der Verbesserung –
5 Millionen Datensätze ?? ⊙▃⊙ – Blueblazer172
Ich denke, diese Frage eignet sich besser für den Stackexchange von codereview, da es sich nicht um einen Fehler in Ihrem Code handelt, sondern um eine Optimierung. – KhorneHoly