mysql 用大量测试数据填充数据库表

jdg4fx2g  于 5个月前  发布在  Mysql
关注(0)|答案(8)|浏览(73)

我需要加载一个包含大量测试数据的表。这将用于测试性能和扩展。
如何为数据库表轻松创建100,000行随机/垃圾数据?

1sbrub3j

1sbrub3j1#

您也可以使用stored procedure。请考虑下表作为示例:

CREATE TABLE your_table (id int NOT NULL PRIMARY KEY AUTO_INCREMENT, val int);

字符串
然后你可以添加一个像这样的存储过程:

DELIMITER $$
CREATE PROCEDURE prepare_data()
BEGIN
  DECLARE i INT DEFAULT 100;

  WHILE i < 100000 DO
    INSERT INTO your_table (val) VALUES (i);
    SET i = i + 1;
  END WHILE;
END$$
DELIMITER ;


当你调用它的时候,你会有10万条记录:

CALL prepare_data();

eqfvzcg8

eqfvzcg82#

对于多行克隆(数据复制),可以使用

DELIMITER $$
CREATE PROCEDURE insert_test_data()
BEGIN
  DECLARE i INT DEFAULT 1;

  WHILE i < 100000 DO
    INSERT INTO `table` (`user_id`, `page_id`, `name`, `description`, `created`)
    SELECT `user_id`, `page_id`, `name`, `description`, `created`
    FROM `table`
    WHERE id = 1;
    SET i = i + 1;
  END WHILE;
END$$
DELIMITER ;
CALL insert_test_data();
DROP PROCEDURE insert_test_data;

字符串

pes8fvy9

pes8fvy93#

下面是纯数学和SQL的解决方案:

create table t1(x int primary key auto_increment);
insert into t1 () values (),(),();

mysql> insert into t1 (x) select x + (select count(*) from t1) from t1;
Query OK, 1265 rows affected (0.01 sec)
Records: 1265  Duplicates: 0  Warnings: 0

mysql> insert into t1 (x) select x + (select count(*) from t1) from t1;
Query OK, 2530 rows affected (0.02 sec)
Records: 2530  Duplicates: 0  Warnings: 0

mysql> insert into t1 (x) select x + (select count(*) from t1) from t1;
Query OK, 5060 rows affected (0.03 sec)
Records: 5060  Duplicates: 0  Warnings: 0

mysql> insert into t1 (x) select x + (select count(*) from t1) from t1;
Query OK, 10120 rows affected (0.05 sec)
Records: 10120  Duplicates: 0  Warnings: 0

mysql> insert into t1 (x) select x + (select count(*) from t1) from t1;
Query OK, 20240 rows affected (0.12 sec)
Records: 20240  Duplicates: 0  Warnings: 0

mysql> insert into t1 (x) select x + (select count(*) from t1) from t1;
Query OK, 40480 rows affected (0.17 sec)
Records: 40480  Duplicates: 0  Warnings: 0

mysql> insert into t1 (x) select x + (select count(*) from t1) from t1;
Query OK, 80960 rows affected (0.31 sec)
Records: 80960  Duplicates: 0  Warnings: 0

mysql> insert into t1 (x) select x + (select count(*) from t1) from t1;
Query OK, 161920 rows affected (0.57 sec)
Records: 161920  Duplicates: 0  Warnings: 0

mysql> insert into t1 (x) select x + (select count(*) from t1) from t1;
Query OK, 323840 rows affected (1.13 sec)
Records: 323840  Duplicates: 0  Warnings: 0

mysql> insert into t1 (x) select x + (select count(*) from t1) from t1;
Query OK, 647680 rows affected (2.33 sec)
Records: 647680  Duplicates: 0  Warnings: 0

字符串

pxiryf3j

pxiryf3j4#

如果你想对数据进行更多的控制,可以尝试这样做(在PHP中):

<?php
$conn = mysql_connect(...);
$num = 100000;

$sql = 'INSERT INTO `table` (`col1`, `col2`, ...) VALUES ';
for ($i = 0; $i < $num; $i++) {
  mysql_query($sql . generate_test_values($i));
}
?>

字符串
其中函数generate_test_values将返回一个格式为“('val1','val2',...)"的字符串。如果这需要很长时间,你可以批量处理它们,这样你就不会进行太多的数据库调用,例如:

for ($i = 0; $i < $num; $i += 10) {
  $values = array();
  for ($j = 0; $j < 10; $j++) {
    $values[] = generate_test_data($i + $j);
  }
  mysql_query($sql . join(", ", $values));
}


只能运行10000个查询,每个查询添加10行。

r3i60tvu

r3i60tvu5#

我真的很喜欢Percona的mysql_random_data_loader实用程序,你可以找到更多关于它的细节here
mysql_random_data_loader是一个连接到mysql数据库并使用随机数据填充指定表的实用程序。如果表中存在外键,它们也将被正确填充。
这个实用程序有一个很酷的功能,数据生成的速度可以是有限的。
例如,要在sakila.film_actor表中以每秒500条记录的速度生成30,000条记录,需要使用以下命令

mysql_random_data_load sakila film_actor 30000 --host=127.0.0.1 --port=3306 --user=my_user --password=my_password --qps=500 --bulk-size=1

字符串
我已经成功地使用这个工具在测试环境中模拟了一个工作负载,方法是针对不同的表在多个线程上以不同的速度运行这个实用程序。
UPD 9/11/2023
mysql有一个内置的负载测试工具mysqlslap。它比mysql_random_data_load简单。它主要用于模拟工作负载,但使用--no-drop选项不会在任务完成时丢弃测试数据。
在50个线程中填充表。

mysqlslap -u user -h localhost -ppass -P 3306 --create-schema=test_db_1 --query="INSERT INTO t (a) VALUES (RAND());" --create="CREATE TABLE t (a INT);" --number-of-queries=5000000 --concurrency=50 --no-drop


在10个线程中填充4个表

mysqlslap -u adm -h localhost -ppass -P 3306 --create-schema=test_db_44 \
--query="INSERT INTO t1 (a) VALUES (RAND()); INSERT INTO t2 (a) VALUES (RAND()); INSERT INTO t3 (a) VALUES (RAND()); INSERT INTO t4 (a) VALUES (RAND()); INSERT INTO t5 (a) VALUES (RAND());" \
--create="CREATE TABLE t1 (a INT); CREATE TABLE t2 (a INT); CREATE TABLE t3 (a INT); CREATE TABLE t4 (a INT); CREATE TABLE t5 (a INT);" \
--number-of-queries=1250000 --concurrency=10 --no-drop


ps.我明白,主要的一点是在更短的时间内创建更多的数据,insert-select的选项是最适合的。但是,这会创建具有很大重复系数的数据,这使得测试不干净,例如,此类数据的压缩比将非常高。

guykilcj

guykilcj6#

尝试filldb
你可以张贴你的模式或使用现有的模式,并产生虚拟数据和出口从这个网站和进口在您的数据库。

gc0ot86w

gc0ot86w7#

create table mydata as select * from information_schema.columns;
insert into mydata select * from mydata;
-- repeating the insert 11 times will give you at least 6 mln rows in the table.

字符串
我非常抱歉,如果这是不合适的,但我想提供一些解释,因为我知道的只是足够解释它,以及如何上面的答案是相当有用的,如果你只了解它做什么。
第一行创建了一个名为mydata的表,它从information_schema中生成列的布局,information_schema存储了关于MYSQL服务器的信息,在本例中,它从information_schema.columns中提取,这使得创建的表不仅具有创建表所需的所有列信息,而且还具有自动创建所需的所有列,非常方便。
第二行以Insert语句开始,该语句现在将针对名为mydata的新表并将Information_schema数据插入表中。最后一行只是一条注解,建议您如果想要生成更多数据,请运行脚本几次。
最后,在我的测试中,这个脚本的一次执行生成了6,956行数据。如果你需要一种快速的方法来生成一些记录,这是一个不错的方法。但是,对于更高级的测试,您可能希望ALTER表包含一个自动递增的主键,这样您就有了一个唯一的索引,因为没有主键的数据库是一个悲伤的数据库。也往往有不可预测的结果,因为可能会有重复的条目。话虽如此,我想提供一些深入了解这段代码,因为我发现它很有用,我想其他人也可能,只要他们花时间解释它是做什么的。大多数人都不喜欢执行代码,他们不知道它会做什么,即使是从一个可信的来源,所以希望其他人也能像我一样发现这个有用。我不是把这个作为“答案”提供,而是作为另一个信息来源,帮助为上面的答案提供一些后勤支持。

cwdobuhd

cwdobuhd8#

这是对@michalzuber答案的一个更高性能的修改。唯一的区别是删除了WHERE id = 1,这样每次运行时插入的内容就可以累积起来。
生成的记录数量为n^2;
因此,对于10次迭代,10^2 = 1024条记录对于20次迭代,20^2 = 1048576条记录,依此类推。

DELIMITER $$
CREATE PROCEDURE insert_test_data()
BEGIN
  DECLARE i INT DEFAULT 1;

  WHILE i <= 10 DO
    INSERT INTO `table` (`user_id`, `page_id`, `name`, `description`, `created`)
    SELECT `user_id`, `page_id`, `name`, `description`, `created`
    FROM `table`;
    SET i = i + 1;
  END WHILE;
END$$
DELIMITER ;
CALL insert_test_data();
DROP PROCEDURE insert_test_data;

字符串

相关问题