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 倍.
总算不用一直等数据插入了.