MySql || 快速创建100w条记录

平时每个开发者都会讨论数据量大时,sql的优化问题。但是并不是每个人都会有100w的数据量可以用来实战,那么今天我们就自己动手,模拟一个100w数据量的表。

  • 创建原理

其实创建的方法有很多,有快的也有慢的。本博客中写的当然不是最快的那个,但确实是比较好操作和理解的。那么我先来说明一下它的原理:它是利用mysql中的在MEMORY引擎的特点,用于快速的插入100w的数据在内存中存放,然后再利用sql插入到目标的表当中。

  • 操作步骤
  1. 创建表t_user,这是用于存放数据的表。
 1 CREATE TABLE `t_user` (
 2   `id` int(11) NOT NULL AUTO_INCREMENT,
 3   `c_user_id` varchar(36) NOT NULL DEFAULT ‘‘,
 4   `c_name` varchar(22) NOT NULL DEFAULT ‘‘,
 5   `c_province_id` int(11) NOT NULL,
 6   `c_city_id` int(11) NOT NULL,
 7   `create_time` datetime NOT NULL,
 8   PRIMARY KEY (`id`) 9 ) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4;

  2.创建内存表t_user_memory,这是用于快速插入数据的表。

1 CREATE TABLE `t_user_memory` (
2   `id` int(11) NOT NULL AUTO_INCREMENT,
3   `c_user_id` varchar(36) NOT NULL DEFAULT ‘‘,
4   `c_name` varchar(22) NOT NULL DEFAULT ‘‘,
5   `c_province_id` int(11) NOT NULL,
6   `c_city_id` int(11) NOT NULL,
7   `create_time` datetime NOT NULL,
8   PRIMARY KEY (`id`)
9 ) ENGINE=MEMORY DEFAULT CHARSET=utf8mb4;

  3.创建随机字符串函数randStr(),用于在给c_name赋值时更加随机。

delimiter $$
CREATE DEFINER=`root`@`%` FUNCTION `randStr`(n INT) RETURNS varchar(255) CHARSET utf8mb4
DETERMINISTIC
BEGIN
 DECLARE chars_str varchar(100) DEFAULT ‘abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789‘;
 DECLARE return_str varchar(255) DEFAULT ‘‘;
 DECLARE i INT DEFAULT 0;
 WHILE i<n DO
     SET return_str = concat(return_str, substring(chars_str, FLOOR(1 + RAND() * 62), 1));
        SET i=i+1;
END WHILE;
RETURN return_str;
END $$

这个函数的语法不用解释也会看得懂,但是还是有几个点需要注意的。

  1. delimiter关键字,这是一个声明结束符的关键字。简单的来说就是,防止和BEGIN和END之间的语句冲突,因为我们希望这里面的语句是连续执行的。
  2. CONCAT(str,str)链接两个字符串组成一个新的字符串。
  3. FLOOR(num)函数,向下取整。例如floor(1.23) = 1 、floor(-1.23) = -2。

  4.创建随机时间函数randDataTime(),为了后期的时间更加随机。

 1 delimiter $$
 2 CREATE DEFINER = `root`@`%` FUNCTION `randDataTime` (sd DATETIME, ed DATETIME) RETURNS datetime DETERMINISTIC
 3 BEGIN
 4     DECLARE
 5         sub INT DEFAULT 0 ;
 6     DECLARE
 7             ret DATETIME ;
 8         SET sub = ABS(
 9             UNIX_TIMESTAMP(ed) - UNIX_TIMESTAMP(sd)
10         ) ;
11         SET ret = DATE_ADD(
12             sd,
13             INTERVAL FLOOR(1 + RAND() *(sub - 1)) SECOND
14         ) ;
15     RETURN ret ;
16 END $$

里面的需要注意的是DATE_ADD(dateTime,INTERVAL  num  SECOND)函数,第一个参数是被添加的时间,第二个参数是一个组合,表明是添加的长度,如:(INTERVAL 1  YEAR)表示在原来的基础上添加一年的时间间隔

  5.创建插入数据存储过程add_t_user_memory (int)

 1 delimiter $$
 2 CREATE DEFINER=`root`@`%` PROCEDURE add_t_user_memory (IN n INT)
 3 BEGIN
 4     DECLARE
 5         i INT DEFAULT 1 ;
 6     WHILE i < n DO
 7         INSERT INTO t_user_memory (
 8             c_user_id,
 9             c_name,
10             c_province_id,
11             c_city_id,
12             create_time
13         )
14     VALUES
15         (
16             uuid(),
17             randStr (20),
18             FLOOR(RAND() * 1000),
19             RAND() * 100,
20             NOW()
21         );
22 SET i = i + 1 ;
23 END
24 WHILE ;
25 END $$
  • 执行过程中的问题

在完成上面的声明之后我们就可以用CALL  add_t_user_memory (1000000)来创建100w的数据啦,这大概需要20分钟的时间。但是在调用的过程中却发现了一个问题如下图所示。

原来是‘t_user_memory‘ 已经满了。它是我在上面定义的用内存存放数据的表,在MYSQL中默认的大小是16MB。这个大小只能放4w多条数据,所以我们要想办法把它扩大。那么可以执行下面语句

1 SET GLOBAL max_heap_table_size = 1024 * 1024 * 1024 * 1;
2
3 #查看当前的设置的大小
4 select @@max_heap_table_size;

注意:修改需要重新链接mysql才能更新修改。这个修改自己机器上玩玩就可以了,在生产环境这么改有什么后果我可不负责。

  • 完善数据库
  1. 执行下面语句,大概需要10s就可以插入到t_user中。
INSERT INTO t_user SELECT * FROM t_user_memory;

  2.打乱创建时间。

#更新年间隔
UPDATE t_user SET create_time=date_add(create_time, interval FLOOR(1 + (RAND() * 4)) year);
#更新秒间隔
UPDATE t_user SET create_time=randDataTime(NOW(),create_time);
  • 完成

这样,我们的百万级数据库就创建完成啦!然后,我们可以将t_user_memory这个表清空,毕竟它是很占内存的,你数据有多少内存就占多少。下次再结合业务试试SQL优化怎么玩。

原文地址:https://www.cnblogs.com/hill1126/p/11334523.html

时间: 2024-10-09 20:14:36

MySql || 快速创建100w条记录的相关文章

MySQL快速生成100W条测试数据

https://blog.csdn.net/qq_16946803/article/details/81870174 1.生成思路利用mysql内存表插入速度快的特点,先利用函数和存储过程在内存表中生成数据,然后再从内存表插入普通表中 2.创建普通表及内存表普通表CREATE TABLE `vote_record` ( `id` INT (11) NOT NULL AUTO_INCREMENT, `user_id` VARCHAR (20) NOT NULL, `vote_id` INT (11

php实现只保留mysql中最新1000条记录

这篇文章主要介绍了php实现只保留mysql中最新1000条记录的方法和相关示例及数据库结构,十分的全面,有需要的小伙伴可以参考下. ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <?php mysql_connect("localhost","root","root"); mysql_select_db("test"); //保留最新的1000条记录 $

odoo 创建一条记录的时候自动增加一个序列号

第一步: 在odoo开发者模式,进入配置设置添加一个序列号,sequence ocde 这个地方的值要与代码里相同 开始是在代码里这样设置的,cwbh是财务编号的字段需求是每次新增自动加1 cwbh = fields.Char(string='Number', required=True, copy=False, readyonly= True default=lambda self:self.env['ir.sequence'].next_by_code('dycrm.cwbh')) 重新启动

Python Flask 向MySQL表里插入一条记录,提示Unknown column &#39;XXX&#39; in &#39;field list

sql =' INSERT INTO `blog`.`user` (`id`, `username`) VALUES (%d, %s)' %(1,username) 我在给username赋值aaabbb后提示:"Unknown column 'aaaabbb' in 'field list'" 找了半天问题,原来是%s没加双引号. 改为如下 sql =' INSERT INTO `blog`.`user` (`id`, `username`) VALUES (%d, "%s

关于Oracle,sqlserver,mysql中查询10-20条记录的写法

一: oracle数据库写法: 1:select * from (select rownum rn ,* from 表名 where?rownum<20?) a? ?where a.rn>10 2:select * from 表名 where rownum<20 minus select * from 表名 where rownum<10 ? 二:SqlServer数据库写法: 1:select top 20 * from tablename where id not?exists

[mysql] 查询前几条记录

From: http://www.cnblogs.com/xuxm2007/archive/2010/11/16/1878211.html SELECT   *   FROM   table   LIMIT   5;           select     *     from     issu_info     limit     0,6             Limit     0,6       这里是对的,显示前6条                   select     *   

快速找到一条记录所在的页码

算出这条记录所在的rowNum,rowNum是连续的,再根据rowNum算出这条记录所在的页码. public int getPageNoByBackId(int noteId,int backId,int pageSize) { StringBuilder sql = new StringBuilder(); sql.append(" select num from ( \n"); sql.append("select ROW_NUMBER() over(order by

mysql 造1亿条记录的单表--大数据表

读写文件 背景及木:现有数据1000w单表,为压力测试准备1亿条数据. 步骤: 1.将1000w条记录,除id外都导入到多个文件中: //DELIMITER DROP PROCEDURE if EXISTS createManyTable; create PROCEDURE createManyTable() BEGIN DECLARE i int; DECLARE fileName VARCHAR(30); set i=1; while i<251 DO SET fileName=CONCAT

mysql left join 多条记录 1:n 的处理方法

一.准备两张表,文章表和评伦表 CREATE TABLE `article` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID', `title` varchar(255) DEFAULT '' COMMENT '文章标题', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文章表'; CREATE TABLE `comment` ( `i