当前位置: 首页 > article >正文

MySQL 构建 1000 万数据太慢?如何快速构建大量模拟数据?

      • 背景
      • 如何快速创建大量数据.

背景

  • 我最近在做MySQL的性能测试的时候需要构建大量数据(1000万以上)

于是我使用gorm的Create方法进行创建

逻辑就是使用一个循环1000万次的for创建对象并调用 create 方法

但是发现一个巨大的问题,创建速度巨慢,几乎1分钟10万条

1000 万条还不等到猴年?

于是我打算使用一种高性能的创建方案

如何快速创建大量数据.

网上创建模拟数据的方式大部分都是建立一个循环,一行行插入,但是这样的效率不高确实

我的方案就是:**一条 insert 命令插入 多条数据(1万 条甚至 10万条)**避免频繁的执行 insert

原代码

package main

import (
	"database/sql"
	"fmt"
	"log"
	"math/rand"
	"time"

	_ "github.com/go-sql-driver/mysql"
)

func generateRandomString(length int) string {
	const chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
	var result string
	for i := 0; i < length; i++ {
		result += string(chars[rand.Intn(len(chars))])
	}
	return result
}

func generateRandomPhoneNumber() string {
	return fmt.Sprintf("1%03d%04d%04d", rand.Intn(1000), rand.Intn(10000), rand.Intn(10000))
}

// 生成批量插入的 query与 args([]interface{})
func generateInsertQueryAndArgs(numRecords int) (string, []interface{}) {
	query := "INSERT INTO `user` (`name`, `tag`, `phone`, `create_time`) VALUES "
	args := make([]interface{}, 0, numRecords*4)
	for i := 0; i < numRecords; i++ {
		name := generateRandomString(10)
		tag := generateRandomString(5)
		phone := generateRandomPhoneNumber()
		createTime := generateRandomDatetime()
		query += "(?, ?, ?, ?)"
		if i < numRecords-1 {
			query += ","
		}
		args = append(args, name, tag, phone, createTime)
	}
	return query, args
}

func generateRandomDatetime() time.Time {
	year := rand.Intn(5) + 2018 // Random year between 2018 and 2022
	month := rand.Intn(12) + 1  // Random month between 1 and 12
	day := rand.Intn(28) + 1    // Random day between 1 and 28 (for simplicity)
	hour := rand.Intn(24)
	minute := rand.Intn(60)
	second := rand.Intn(60)

	return time.Date(year, time.Month(month), day, hour, minute, second, 0, time.UTC)
}

func main() {
	// Open MySQL connection
	dsn := "master:123456@tcp(127.0.0.1:3306)/000?parseTime=true"
	db, err := sql.Open("mysql", dsn)
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	// Check if the connection is working
	if err := db.Ping(); err != nil {
		log.Fatal(err)
	}

	// Insert 1000万条数据
	for i := 0; i < 1000; i++ {
		// 生成批量插入的 query与 args([]interface{})
		query, args := generateInsertQueryAndArgs(10000)
		// 执行插入操作
		_, err := db.Exec(query, args...)
		if err != nil {
			log.Fatal(err)
		}
		if i%10 == 0 {
			log.Println(i, "万条")
		}
	}

	log.Println("Data insertion completed.")
	//插入耗时:1000万条数据,耗时4分9秒钟
}

平均 2-3 秒钟插入 10 万条数据,1000 万数据 4 分钟就好了,性能高了 25 倍.

总算不用一直等数据插入了.


http://www.kler.cn/a/454950.html

相关文章:

  • 打破视障壁垒,百度文心快码无障碍版本助力视障IT从业者就业无“碍”
  • 理解有放回和无放回抽样 (Python)
  • 小波分析算法
  • 【Leetcode 热题 100】46. 全排列
  • C++ —— 模板类与友元
  • 数字化什么意思?从基础概念到行业应用的全面解读
  • Linux应用软件编程-多任务处理(进程)
  • 代码随想录Day52 101. 孤岛的总面积,102. 沉没孤岛,103. 水流问题,104.建造最大岛屿。
  • qt+Linux+arm多核CPU 亲和性
  • Python异常处理在“简易记事本”项目中的应用
  • 摄影构图与拍摄
  • XTUOJ 三角数
  • 数据分析篇001
  • 设计模式--装饰器模式【结构型模式】
  • MCS-51单片机常用汇编指令和特殊功能寄存器~
  • STM32开发笔记123:使用FlyMcu下载程序
  • 代码随想录Day49 42. 接雨水,84.柱状图中最大的矩形。
  • macrodroid通过http请求控制手机运行宏
  • Zookeeper下面的lib
  • 初学elasticsearch