为虚拟数据创建批量MySQL插入脚本

时间:2015-04-26 11:23:29

标签: php mysql batch-processing

我需要测试一些大型数据集(1M - 50M)上的一些查询,并且我在编写将执行此操作快速的流程时遇到问题。

我有以下代码,稍微修改了我在其他SO帖子中找到的版本:

set_time_limit(0);

$db_host = 'localhost';
$db_name = 'test';

$db_user = '';
$db_pass = '';

$entries = 1000000;
$entry_words_min = 250;
$entry_words_max = 1000;

/*
  End configuration
*/

function get_rand_word( $len_min, $len_max ) {
    for ( $i = 0; $i < ( rand( 0, $len_max - $len_min ) + $len_min ); $i++ ) {
        $word .= chr(rand(65, 90));
    }
    return $word;
}
function get_title() {
    for ( $i = 0; $i < ( rand( 4, 10 ) ); $i++ ) {
        $title .= get_rand_word( 2, 9 ) . ' ';
    }
    return $title;
}
function get_fulltext() {
    for ( $i = 0; $i < ( rand( 250, 500 ) ); $i++ ) {
        $fulltext .= get_rand_word( 2, 9 ) . ' ';
    }
    return $fulltext;
}

$dsn = 'mysql:dbname=' . $db_name . ';host=' . $db_host;

try {
    $dbh = new PDO($dsn, $db_user, $db_pass);
} catch (PDOException $e) {
    echo 'Connection failed: ' . $e->getMessage();
    die();
}

$sth = $dbh->prepare('INSERT INTO `sphinx` (`some_id`,`title`,`content`) VALUES (:some_id, :title, :content)');

$counter = 0;

for ( $i = 0; $i < $entries; $i++ ) {
    $sth->execute(array(
        ':some_id' => mt_rand(1,65000),
        ':title' => get_title(),
        ':content' => get_fulltext()
    ));
    $counter++;
}

echo $counter . ' rows inserted';

然而,这在插入时相当慢;插入500k行只需要几个小时。我知道我可以写一个批量插入查询,但我不认为为一百万个插入编写一个这样的好主意;我想它可以一次分解为10k,但想检查是否有更好/更清洁的方法可用。

2 个答案:

答案 0 :(得分:0)

您可以使用https://github.com/fzaninotto/Faker。您可以根据需要制作循环并伪造尽可能多的记录。全部都是随机数据。

答案 1 :(得分:0)

首先,我建议测量时间,在第n次插入后,让我们说每10000个循环索引,以查看任何异常。

$start = microtime(true);
for ($i = 0; $i < $entries; $i++) {
    $sth->execute(array(
        ':some_id' => mt_rand(1,65000),
        ':title' => get_title(),
        ':content' => get_fulltext()
    ));
    if ($i % 10000 === 9999) {
        $end = microtime(true);
        echo $i . ' ' . ($end - $start) . '<br>';
    }
    $counter++;
}

也可能是数据库类型或索引甚至硬盘驱动器的问题。最知名的类型比较: MyISAM versus InnoDB