golang 高性能的 MySQL 数据导出

需求

  • 导出 MySQL 数据

分析:

  • 一次性 select 大量数据带来的问题

性能问题:

数据库负载:大量数据查询会增加数据库的CPU、内存和I/O负担,可能影响其他操作。

网络传输:大数据量传输会占用大量带宽,导致网络延迟或超时。

内存消耗:

服务器内存: 消耗太大,影响其他业务运行

导出方式对比

  • 条件:
  • 200 万数据
  • 查询全表耗时 3s
方案1:快照导出(耗时:1.5s)
go 复制代码
data, err := db.Query("select * from user2")
	if err != nil {
		log.Fatal("err1:", err)
	}
	defer data.Close()

	columns, err := data.Columns()
	if err != nil {
		log.Printf("[error] %v \n", err)
	}

	l := len(columns)

	val := &User{}
	valPointer := make([]interface{}, l)
	valPointer[0] = &val.Id
	valPointer[1] = &val.Name
	valPointer[2] = &val.Tag
	valPointer[3] = &val.Phone
	valPointer[4] = &val.Create_time

	//计数
	num := 0

	for data.Next() {
		err := data.Scan(valPointer...)
		if err != nil {
			log.Fatal("err5:", err)
		}
	}
方案2: 偏移分页(耗时:4s)
go 复制代码
	// 定义分页参数
	starId := 0
	pageSize := 2000
	// 定义查询条件
	var users []User
	// 执行分页查询
	for {
		result := db.Limit(pageSize).Where("id >= ?", starId).Find(&users)
		if result.Error != nil {
			log.Fatal("err5:", result.Error)
		}

		if len(users) < pageSize {
			break
		}
		starId = users[len(users)-1].Id
	}
方案 3:普通分页(耗时:4min40s)
go 复制代码
// 定义分页参数
	page := 1
	pageSize := 2000

	// 导出数据
	for {
		var users []User
		result := db.Offset((page - 1) * pageSize).Limit(pageSize).Find(&users)
		if result.Error != nil {
			log.Fatal("err5:", result.Error)
		}
		if len(users) < pageSize {
			break
		}
		page++
	}
相关推荐
secondyoung8 分钟前
Markdown转换为Word:Pandoc模板使用指南
开发语言·经验分享·笔记·c#·编辑器·word·markdown
lly20240610 分钟前
Django ORM - 聚合查询
开发语言
胖咕噜的稞达鸭1 小时前
算法入门:专题攻克主题一---双指针(2)快乐数 呈最多水的容器
开发语言·数据结构·c++·算法
沐知全栈开发1 小时前
Perl 简介
开发语言
-雷阵雨-2 小时前
数据结构——优先级队列(堆)
java·开发语言·数据结构·intellij-idea
步行cgn2 小时前
Java项目包结构设计与功能划分详解
java·开发语言·架构·mvc
ss2732 小时前
手写MyBatis第92弹:SqlSource体系、SqlNode树与Trim标签实现原理全揭秘
java·开发语言
2501_915909062 小时前
iOS 抓包工具有哪些?实战对比、场景分工与开发者排查流程
android·开发语言·ios·小程序·uni-app·php·iphone
charlie1145141913 小时前
精读C++设计模式20 —— 结构型设计模式:桥接模式
开发语言·c++·学习·设计模式·桥接模式·c++23·概论
heyCHEEMS3 小时前
最长连续序列 Java
java·开发语言·算法