【发布时间】:2017-04-24 23:29:24
【问题描述】:
我有一个任务要练习。生成 500 万条记录:string (15), string (15), int (min: 1 max: 99) 并将它们存储在数据库 postgresql 中。 我的脚本的第一个版本是 500 万的估计时间:16120 秒。
编辑(2015 年 12 月 12 日 11:50):目前经过多次优化:80 秒。
为了达到预期的效果,我应该改变什么?
下面我展示了代码的最优化版本。
// 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();
}
}
也许我云使用了除 INSERT 之外的其他东西?
编辑:问题解决了! 2016年12月19日 script relase 1.0 source
重要!在 cmd 底部命令中运行此脚本之前执行一次
mkdir /tmp/ram
mount -t tmpfs -o size=512m tmpfs /tmp/ram
生成数据:
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();
}
}
插入行:
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);
}
【问题讨论】:
-
在文件中加载数据并在插入后添加索引是改进点
-
500 万条记录?? ⊙▃⊙
-
我认为这个问题更适合 codereview stackexchange,因为我们不是在处理代码中的错误,而是在优化。
-
377 秒 - 运行脚本时间 362 秒 - 运行插入 12 秒 - randomString() 1.5 秒 - randomAge()
标签: php postgresql optimization pdo transactions