我需要加载一个包含大量测试数据的表。这将用于测试性能和扩展。如何为数据库表轻松创建100,000行随机/垃圾数据?
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 ;
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();
型
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;
CREATE PROCEDURE insert_test_data()
DECLARE i INT DEFAULT 1;
INSERT INTO `table` (`user_id`, `page_id`, `name`, `description`, `created`)
SELECT `user_id`, `page_id`, `name`, `description`, `created`
FROM `table`
WHERE id = 1;
CALL insert_test_data();
DROP PROCEDURE insert_test_data;
字符串
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: 0mysql> 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: 0mysql> 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: 0mysql> 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: 0mysql> 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: 0mysql> 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: 0mysql> 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: 0mysql> 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: 0mysql> 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: 0mysql> 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
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
Query OK, 2530 rows affected (0.02 sec)
Records: 2530 Duplicates: 0 Warnings: 0
Query OK, 5060 rows affected (0.03 sec)
Records: 5060 Duplicates: 0 Warnings: 0
Query OK, 10120 rows affected (0.05 sec)
Records: 10120 Duplicates: 0 Warnings: 0
Query OK, 20240 rows affected (0.12 sec)
Records: 20240 Duplicates: 0 Warnings: 0
Query OK, 40480 rows affected (0.17 sec)
Records: 40480 Duplicates: 0 Warnings: 0
Query OK, 80960 rows affected (0.31 sec)
Records: 80960 Duplicates: 0 Warnings: 0
Query OK, 161920 rows affected (0.57 sec)
Records: 161920 Duplicates: 0 Warnings: 0
Query OK, 323840 rows affected (1.13 sec)
Records: 323840 Duplicates: 0 Warnings: 0
Query OK, 647680 rows affected (2.33 sec)
Records: 647680 Duplicates: 0 Warnings: 0
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));}?>
<?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));}
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行。
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/2023mysql有一个内置的负载测试工具mysqlslap。它比mysql_random_data_load简单。它主要用于模拟工作负载,但使用--no-drop选项不会在任务完成时丢弃测试数据。在50个线程中填充表。
mysql_random_data_load
--no-drop
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
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的选项是最适合的。但是,这会创建具有很大重复系数的数据,这使得测试不干净,例如,此类数据的压缩比将非常高。
insert-select
guykilcj6#
尝试filldb你可以张贴你的模式或使用现有的模式,并产生虚拟数据和出口从这个网站和进口在您的数据库。
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.
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表包含一个自动递增的主键,这样您就有了一个唯一的索引,因为没有主键的数据库是一个悲伤的数据库。也往往有不可预测的结果,因为可能会有重复的条目。话虽如此,我想提供一些深入了解这段代码,因为我发现它很有用,我想其他人也可能,只要他们花时间解释它是做什么的。大多数人都不喜欢执行代码,他们不知道它会做什么,即使是从一个可信的来源,所以希望其他人也能像我一样发现这个有用。我不是把这个作为“答案”提供,而是作为另一个信息来源,帮助为上面的答案提供一些后勤支持。
mydata
information_schema
information_schema.columns
Insert
Information_schema
ALTER
cwdobuhd8#
这是对@michalzuber答案的一个更高性能的修改。唯一的区别是删除了WHERE id = 1,这样每次运行时插入的内容就可以累积起来。生成的记录数量为n^2;因此,对于10次迭代,10^2 = 1024条记录对于20次迭代,20^2 = 1048576条记录,依此类推。
WHERE id = 1
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;
WHILE i <= 10 DO
FROM `table`;
8条答案
按热度按时间1sbrub3j1#
您也可以使用stored procedure。请考虑下表作为示例:
字符串
然后你可以添加一个像这样的存储过程:
型
当你调用它的时候,你会有10万条记录:
型
eqfvzcg82#
对于多行克隆(数据复制),可以使用
字符串
pes8fvy93#
下面是纯数学和SQL的解决方案:
字符串
pxiryf3j4#
如果你想对数据进行更多的控制,可以尝试这样做(在PHP中):
字符串
其中函数generate_test_values将返回一个格式为“('val1','val2',...)"的字符串。如果这需要很长时间,你可以批量处理它们,这样你就不会进行太多的数据库调用,例如:
型
只能运行10000个查询,每个查询添加10行。
r3i60tvu5#
我真的很喜欢Percona的mysql_random_data_loader实用程序,你可以找到更多关于它的细节here。
mysql_random_data_loader是一个连接到mysql数据库并使用随机数据填充指定表的实用程序。如果表中存在外键,它们也将被正确填充。
这个实用程序有一个很酷的功能,数据生成的速度可以是有限的。
例如,要在sakila.film_actor表中以每秒500条记录的速度生成30,000条记录,需要使用以下命令
字符串
我已经成功地使用这个工具在测试环境中模拟了一个工作负载,方法是针对不同的表在多个线程上以不同的速度运行这个实用程序。
UPD 9/11/2023
mysql有一个内置的负载测试工具mysqlslap。它比
mysql_random_data_load
简单。它主要用于模拟工作负载,但使用--no-drop
选项不会在任务完成时丢弃测试数据。在50个线程中填充表。
型
在10个线程中填充4个表
型
ps.我明白,主要的一点是在更短的时间内创建更多的数据,
insert-select
的选项是最适合的。但是,这会创建具有很大重复系数的数据,这使得测试不干净,例如,此类数据的压缩比将非常高。guykilcj6#
尝试filldb
你可以张贴你的模式或使用现有的模式,并产生虚拟数据和出口从这个网站和进口在您的数据库。
gc0ot86w7#
字符串
我非常抱歉,如果这是不合适的,但我想提供一些解释,因为我知道的只是足够解释它,以及如何上面的答案是相当有用的,如果你只了解它做什么。
第一行创建了一个名为
mydata
的表,它从information_schema
中生成列的布局,information_schema
存储了关于MYSQL服务器的信息,在本例中,它从information_schema.columns
中提取,这使得创建的表不仅具有创建表所需的所有列信息,而且还具有自动创建所需的所有列,非常方便。第二行以
Insert
语句开始,该语句现在将针对名为mydata
的新表并将Information_schema
数据插入表中。最后一行只是一条注解,建议您如果想要生成更多数据,请运行脚本几次。最后,在我的测试中,这个脚本的一次执行生成了6,956行数据。如果你需要一种快速的方法来生成一些记录,这是一个不错的方法。但是,对于更高级的测试,您可能希望
ALTER
表包含一个自动递增的主键,这样您就有了一个唯一的索引,因为没有主键的数据库是一个悲伤的数据库。也往往有不可预测的结果,因为可能会有重复的条目。话虽如此,我想提供一些深入了解这段代码,因为我发现它很有用,我想其他人也可能,只要他们花时间解释它是做什么的。大多数人都不喜欢执行代码,他们不知道它会做什么,即使是从一个可信的来源,所以希望其他人也能像我一样发现这个有用。我不是把这个作为“答案”提供,而是作为另一个信息来源,帮助为上面的答案提供一些后勤支持。cwdobuhd8#
这是对@michalzuber答案的一个更高性能的修改。唯一的区别是删除了
WHERE id = 1
,这样每次运行时插入的内容就可以累积起来。生成的记录数量为n^2;
因此,对于10次迭代,10^2 = 1024条记录对于20次迭代,20^2 = 1048576条记录,依此类推。
字符串