从PHP脚本创建一个非常大的MySQL数据库

时间:2011-09-09 21:33:58

标签: php mysql

请耐心等待这个问题。

我正在寻找一个相对较大的MySQL数据库,我想用它来做一些性能测试。顺便说一句,我正在使用Ubuntu 11.04。

我想创建大约6个表,每个表有大约5000万条记录。每个表格大约有10列。数据只是随机数据。

但是,我不知道如何才能做到这一点。我是否使用PHP和循环INSERT查询(绑定到超时)?或者,如果效率低下,有没有办法通过命令行实用程序或shell脚本来实现?

我真的很感激一些指导。

提前致谢。

8 个答案:

答案 0 :(得分:6)

mysql_import就是你想要的。查看this以获取完整信息。这是命令行,非常快。

答案 1 :(得分:5)

命令行模式通常会禁用超时,因为它可以防止关闭网络服务器,这在命令行中不适用。

你可以用PHP来做,虽然生成“随机”数据会很昂贵。这些信息有多随机?您可以轻松地从/ dev / random读取并获取“垃圾”,但它不是“良好”随机性的来源(您可能需要/ dev / urandom,但如果没有足够的熵可用,则会阻止做好垃圾)。

只需确保您在表上禁用了键,因为保持这些键是最新的将是插入操作的主要拖累。您可以在填充数据集后添加/启用密钥。

答案 2 :(得分:1)

如果你想要以php方式运行,你可以这样做:

<?php
//Edit Following
$millionsOfRows = 2;
$InsertBatchSize = 1000;
$table = 'ATable';
$RandStrLength = 10;
$timeOut = 0; //set 0 for no timeout
$columns = array('col1','col2','etc');

//Mysql Settings
$username = "root";
$password = "";
$database = "ADatabase";
$server   = "localhost";

//Don't edit below

$letters = range('a','z');
$rows = $millionsOfRows * 1000000;
$colCount = count($columns);
$valueArray = array();

$con = @mysql_connect($server, $username, $password) or die('Error accessing database: '.mysql_error());
@mysql_select_db($database) or die ('Couldn\'t connect to database: '.mysql_error());

set_time_limit($timeOut);

for ($i = 0;$i<$rows;$i++)
{
    $values = array();
    for ($k = 0; $k<$colCount;$k++)
        $values[] = RandomString();
    $valueArray[] = "('".implode("', '", $values)."')";

    if ($i > 0 && ($i % $InsertBatchSize) == 0)
    {   
        echo "--".$i/$InsertBatchSize."--";
        $sql = "INSERT INTO `$table` (`".implode('`,`',$columns)."`) VALUES ".implode(',',$valueArray);
        mysql_query($sql);
        echo $sql."<BR/><BR/>";
        $valueArray = array();
    }
}
mysql_close($con);
function RandomString ()
{
    global $RandStrLength, $letters;

    $str = "";
    for ($i = 0;$i<$RandStrLength;$i++)
        $str .= $letters[rand(0,25)];
    return $str;
}

当然,您可以使用已创建的数据集,例如NorthWind数据库。

答案 3 :(得分:1)

您需要做的就是从命令行启动脚本,如下所示:

php -q generator.php

它可以是一个简单的php文件,如下所示:

<?php

$fid = fopen("query.sql", "w");
fputs($fid, "create table a (id int not null auto_increment primary key, b int, c, int);\n");
for ($i = 0; $i < 50000000; $i++){
    fputs($fid, "insert into table a (b,c) values (" . rand(0,1000) . ", " . rand(0,1000) . ")\n");
}
fclose($fid);
exec("mysql -u$user -p$password $db < query.sql");

答案 4 :(得分:0)

我只想指出http://www.mysqldumper.net/这是一个允许您使用PHP备份和恢复大型数据库的工具。

脚本有一些机制可以规避PHP的最长执行时间 - &gt;非常值得一看。

这不是用于生成数据的解决方案,而是用于导入/导出的很好的解决方案。

答案 5 :(得分:0)

  

我是否使用PHP并循环INSERT查询(绑定到超时)

当然,通过网络服务器介导的重新设置运行长持续时间的脚本并不是一个好主意。但PHP可以编译为run from the command line - 事实上,PHP的大多数发行版都捆绑了这个。

您需要做很多事情来提高效率,确切地说,哪些因素会影响数据集的填充(例如,只需一次,批量添加很多)。但是对于单个加载,您可能需要查看mysqldump的输出(注意禁用,启用索引,多个插入行)并在PHP中重新创建它,而不是从PHP直接连接到数据库。

答案 6 :(得分:0)

我认为这个问题没有意义,特别是在为此提出赏金时。

正如他们所说,“最好是好人的敌人”

十天前你问过这个问题 如果你只是使用你所拥有的任何代码,你已经拥有了你的表,甚至完成了你的测试。但是你失去了那么多时间,徒劳无功。这超出了我的理解。

至于你一直要求的方法(只是为了远离所有这些自我指定的主持人),有一些陈述可以作为思考的食物:

  • mysql自己的方法一般认为更有效。
  • mysql可以使用INSERT ... SELECT语法将表中的所有数据插入到另一个数据中。因此,您只需要运行大约30个查询即可获得50万条记录。
  • 并且确定mysql也可以复制整个表格。
  • 请记住,在创建表时应该没有索引。

答案 7 :(得分:-1)

在一个查询中运行多个插入可能是最快的:

INSERT INTO `test` VALUES
    (1,2,3,4,5,6,7,8,9,0),
    (1,2,3,4,5,6,7,8,9,0),
     .....
    (1,2,3,4,5,6,7,8,9,0)

我创建了一个PHP脚本来执行此操作。首先,我尝试构建一个可容纳100万次插入但仍失败的查询。然后我尝试了100 thousend,它又失败了。 50 thousends也不这样做。我的巢尝试是10​​ 000,它工作正常。我想我正在达到从PHP到MySQL的传输限制。这是代码:

<?php
set_time_limit(0);
ini_set('memory_limit', -1);
define('NUM_INSERTS_IN_QUERY', 10000);
define('NUM_QUERIES', 100);

// build query
$time = microtime(true);
$queries =  array();
for($i = 0; $i < NUM_QUERIES; $i++){
    $queries[$i] = 'INSERT INTO `test` VALUES ';
    for($j = 0; $j < NUM_INSERTS_IN_QUERY; $j++){
            $queries[$i] .= '(1,2,3,4,5,6,7,8,9,0),';
    }
    $queries[$i] = rtrim($queries[$i], ',');
}

echo "Building query took " . (microtime(true) - $time) . " seconds\n";

mysql_connect('localhost', 'root', '') or die(mysql_error());
mysql_select_db('store') or die(mysql_error());
mysql_query('DELETE FROM `test`') or die(mysql_error());

// execute the query
$time = microtime(true);
for($i = 0; $i < NUM_QUERIES; $i++){
    mysql_query($queries[$i]) or die(mysql_error());
    // verify all rows inserted
    if(mysql_affected_rows() != NUM_INSERTS_IN_QUERY){
            echo "ERROR: on run $i not all rows inserted (" . mysql_affected_rows() . ")\n";
            exit;
    }
}

echo "Executing query took " . (microtime(true) - $time) . " seconds\n";
$result = mysql_query('SELECT count(*) FROM `test`') or die(mysql_error());
$row = mysql_fetch_row($result);
echo "Total number of rows in table: {$row[0]}\n";
echo "Total memory used in bytes: " . memory_get_usage() . "\n";
?>

我的Win 7开发机器上的结果是:

Building query took 0.30241012573242 seconds
Executing query took 5.6592788696289 seconds
Total number of rows in table: 1000000
Total memory used in bytes: 22396560

因此,对于1密耳的插入物,需要5秒半。然后我用这个设置运行它:

define('NUM_INSERTS_IN_QUERY', 1);
define('NUM_QUERIES', 1000000);

基本上每个查询执行一次插入。结果是:

Building query took 1.6551470756531 seconds
Executing query took 77.895285844803 seconds
Total number of rows in table: 1000000
Total memory used in bytes: 140579784

然后我试图创建一个文件,其中每个查询都有一个插入,如@jancha所示。我的代码略有修改:

$fid = fopen("query.sql", "w");
fputs($fid, "use store;");
for($i = 0; $i < 1000000; $i++){
    fputs($fid, "insert into `test` values (1,2,3,4,5,6,7,8,9,0);\n");
}
fclose($fid);
$time = microtime(true);
exec("mysql -uroot < query.sql");
echo "Executing query took " . (microtime(true) - $time) . " seconds\n";

结果是:

Executing query took 79.207592964172 seconds

与通过PHP执行查询相同。因此,最快的方法可能是在一个查询中进行多次插入,使用PHP进行工作不应该是一个问题。