前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >数据库中千万数据常见问题以及如何解决(超详细,附导入数据教程)

数据库中千万数据常见问题以及如何解决(超详细,附导入数据教程)

原创
作者头像
天下之猴
发布于 2024-09-06 12:40:58
发布于 2024-09-06 12:40:58
860
举报

提前准备

本次我们采用从文件导入数据到数据库中的方式,LOAD DATA INFILE,我们先在IDEA中生成要导入到mysql中去的数据

代码语言:txt
AI代码解释
复制
public static void main(String[] args) {
		//procedure_partition_test2_188||100188||test_模块||test_模块_方法||SEARCH||SUCCESS||2020-10-27 19:38:54||2020-10-27 19:38:54
		String sdf = "yyyy-MM-dd HH:mm:ss";
		Date date = new Date();
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);

		SimpleDateFormat dateFormat = new SimpleDateFormat(sdf);
		File file = new File("C:\\Users\\12192\\Desktop\\load_data.txt");
		String center = "||100188||test_模块||test_模块_方法||SEARCH||SUCCESS||";
		long start = System.currentTimeMillis();
		System.out.println("start:[" + start + "]");
		try {
			PrintWriter pfp = new PrintWriter(file, "UTF-8");
			for (int j = 0; j < 30; j++) {
				String id_prefix = "procedure_partition_test" + j + "_";
				calendar.add(Calendar.DAY_OF_MONTH, -1);
				Date time = calendar.getTime();
				String yesterday = dateFormat.format(time);
				String start_datetime = yesterday;
				String end_datetime = yesterday;
				for (int i = 0; i < 300000; i++) {
					StringBuffer sb = new StringBuffer();
					sb.append(id_prefix).append(i).append(center).append(start_datetime).append("||").append(end_datetime);
					pfp.print(sb.toString() + "\n");
				}
			}
			pfp.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}

		long end = System.currentTimeMillis();
		System.out.println("end:[" + end + "]");
		System.out.println("耗时:[" + (end - start) / 1000 + "s]");

	}

可以看到我们往文件写入900w数据只花了4s,接着将文件中的数据写入到mysql中去

接着数据库打开本地数据加载

代码语言:txt
AI代码解释
复制
set global local_infile=1;

看看有没有打开成功

代码语言:txt
AI代码解释
复制
show global variables like 'local_infile';

再将文件中的数据导入的数据库中

代码语言:txt
AI代码解释
复制
load data local infile 'C:\\Users\\12192\\Desktop\\load_data.txt' into table igs_sm_interface_access_log
CHARACTER SET utf8 -- 可选,避免中文乱码问题
FIELDS TERMINATED BY '||' -- 字段分隔符,每个字段(列)以什么字符分隔,默认是 \t
    OPTIONALLY ENCLOSED BY '' -- 文本限定符,每个字段被什么字符包围,默认是空字符
    ESCAPED BY '\\' -- 转义符,默认是 \
LINES TERMINATED BY '\n' -- 记录分隔符,如字段本身也含\n,那么应先去除,否则load data 会误将其视作另一行记录进行导入
(
    interface_request_seq,
    user_id,
    interface_access_func_name_cn,
    interface_access_method_name_cn,
    interface_access_method_type_name_en,
    interface_response_status_cd,
    begin_datetime,
    end_datetime
) -- 每一行文本按顺序对应的表字段,建议不要省略

可以看到900w数据导入还是很快的,这种方式在导入大量数据时要比之前提到的分批导入还快,接下来我们来一起看看千万级数据查询所出现的问题,以及如何优化

近千万数据的导入花费时长
近千万数据的导入花费时长

深分页问题

话不多上,上图更直观,深分页问题故名思意,就是当数据多到一定程度时,常规的分页查询,越往后所需要的时间就越长

下面是数据量不同同,偏移量相同,以及数据量相同偏量不同的比较

数据量不同,偏移量相同
数据量不同,偏移量相同
数据量相同,偏移量不同
数据量相同,偏移量不同

可以知道数据量和偏移量都会影响到mysql查询的速度

使用具体字段减少回表操作

回表操作就是当你sql写*号时,mysql会去查该表的元数据,将所有字段添加进去,可以看到单线程时差距0.02秒,但是当并发量上去之后,该操作还是能节省不少时间的

回表与不回表的对比
回表与不回表的对比

添加索引,按需查找字段(效果明显)

索引字段与非索引字段查询对比
索引字段与非索引字段查询对比

接下来我们给user_id添加上索引试试,可以看到,添加上了索引之后查询时间有了很明显的优化

未添加索引
未添加索引
设置为索引之后
设置为索引之后

使用游标查询(效果明显)

游标查询即,如果有某个字段是递增的的话,我们只需要维护查询结果的最后一条数据的id是多少,那么我们下次直接将该ID作为下一次查询的条件即可

为什么通过where筛选之后,再进行limit速度会快这么多???

想弄清这个问题,我们需要知道where和limit在mysql中是如何执行的,想弄明白这个,我么就需要知道mysql的service层和存储引擎层,话不多说上实例,有下面查询语句,他在mysql中是如何执行的呢?

代码语言:txt
AI代码解释
复制
select * from table where key > 1 and key < 100 and orther_key != 520;
//key是二级索引字段(非主键的索引),orther为非索引字段
  1. service层告诉存储引擎层:"菜贩子,你先找个鸡蛋我尝尝鲜(返回满足二级索引的第一条数据,非索引字段由service层判断),顺便给我讲讲这个鸡蛋的故事(进行回表操作,详细字段)"
  2. 存储引擎层找到了满足二级索引的鸡蛋后告诉service层:"客户你好,这是我们的尝鲜蛋(满足where中的二级索引),你先常常,这鸡蛋无菌,健康(告诉了service层记录中有哪些字段,也就是回表操作)"
  3. servece层:"你这鸡蛋不够圆啊(不满足我的非索引字段的条件,也就是orther != 520),这个我不要,你继续给我拿"
  4. 存储引擎层:"好好好,我再给你拿一个"
  5. 就这样,他们一来一回,终于service层买到了所有满足条件的鸡蛋

有人问,不是我寻思你这也没说limit啊,不急我们接着看,如果我的语句添加limit之后会是什么样子的呢?

代码语言:txt
AI代码解释
复制
select * from table where key > 1 and key < 100 and orther_key != 520 limt 100000, 100;
//key是二级索引字段(非主键的索引),orther为非索引字段
  1. service层告诉存储引擎层:"菜贩子,你先找个鸡蛋我尝尝鲜(返回满足二级索引的第一条数据,非索引字段由service层判断),顺便给我讲讲这个鸡蛋的故事(进行回表操作,注意:回表操作只会在满足条件的字段上进行!!!!!!!!!)"
  2. 存储引擎层找到了满足二级索引的鸡蛋后告诉service层:"客户你好,我找了一个,满足您条件的鸡蛋,但是你先别急,我先给你存着,满100000个之后再把后面满意的100个鸡蛋一次给你
  3. 就这样,limit一直维护,进行了1000000次回表操作之后,终于,又找了100个鸡蛋,给了service层

可以看到为什么这两种差距很大了吧,limit是把满足条件的数据积攒起来,并且这些数据也还执行了回表(如果查询字段为非索引的话),而where只需要找到满足条件的,再对需要的数据条数进行回表也就是直接limit 100,

PS:小白,有错误请多多指正,立马了解改正!!!!持续更新中.............


参考连接

mysql导入千万级数据实操 - 习惯沉淀 - 博客园 (cnblogs.com)

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
掌握高性能SQL的34个秘诀🚀多维度优化与全方位指南
本篇文章从数据库表结构设计、索引、使用等多个维度总结出高性能SQL的34个秘诀,助你轻松掌握高性能SQL
菜菜的后端私房菜
2024/06/24
7120
MySQL的优化利器⭐️索引条件下推,千万数据下性能提升273%🚀
时间类型:MySQL字段的时间类型该如何选择?千万数据下性能提升10%~30%🚀
菜菜的后端私房菜
2024/06/12
5531
MySQL深分页,limit 100000,10 优化
我们日常做分页需求时,一般会用limit实现,但是当偏移量特别大的时候,查询效率就变得低下。本文将分4个方案,讨论如何优化MySQL百万数据的深分页问题.
寻求出路的程序媛
2024/06/05
9280
MySQL深分页,limit 100000,10 优化
实战!聊聊如何解决MySQL深分页问题
我们日常做分页需求时,一般会用limit实现,但是当偏移量特别大的时候,查询效率就变得低下。本文将分4个方案,讨论如何优化MySQL百万数据的深分页问题,并附上最近优化生产慢SQL的实战案例。
玖柒的小窝
2021/09/27
1.7K1
实战!聊聊如何解决MySQL深分页问题
常用的数据库应用设计优化方法
常用的数据库应用设计优化方法 水平拆分,分库分表 增加缓存层,减少数据库的访问次数,大部分的查询访问ckv,更新操作异步更新到db 读写分离,实现在线访问和离线访问的隔离,避免相互影响,需要注意实例间同步时延的问题 表结构设计优化 主键设计:使用自增id主键 推荐使用自增id主键的原因: InnoDB数据是按照主键聚簇的,数据在物理上按照主键大小顺序存储,使用其他列或者组合无法保证顺序插入,随机IO导致插入性能下降 所有二级索引都存储了主键的,采用二级索引查询,首先找到的主键,然后通过主键定位数据
vincehuang
2020/03/15
6410
MySQL 的回表、覆盖索引、索引下推
假如age和user_name两个字段是个联合索引,我们通过age=18这个索引找到了二级索引树对应页所在的数据,但是由于user_name是模糊查询,导致了这个字段的索引失效,我们得到了二级索引的这一页中age=18的很多个数据(主键id),我们通过这些主键ID回到主键索引树里再查表里的数据,这个操作就是回表。
向着百万年薪努力的小赵
2022/12/02
1.5K0
MySQL 的回表、覆盖索引、索引下推
老大问我:“建表为啥还设置个自增 id ?用流水号当主键不正好么?”
" 又要开始新项目了,一顿操作猛如虎,梳理流程加画图。这不,开始对流程及表结构了。
why技术
2020/11/02
2K0
老大问我:“建表为啥还设置个自增 id ?用流水号当主键不正好么?”
关系型数据库的瓶颈 与 优化
造成第三条语句执行时间如此长的主要原因就是大量的 OR 语句会导致 SQL 解析非常耗时.
BUG弄潮儿
2021/09/10
1.5K0
关系型数据库的瓶颈 与 优化
从数据页和B+树的角度看索引失效原因
文章开头的面试场景不是我编出来的,兄弟们,刚毕业一两年面试的我就出现过这种问题。仅仅问你失效场景,只要准备过面试的人都能答出来。但是再往下问问,就不知道怎么答了。
小许code
2023/08/07
7130
从数据页和B+树的角度看索引失效原因
数据库索引,真的越建越好吗?
索引是提高关系型数据库查询性能的利器,但其并非银弹,必须精通其原理,才能发挥奇效。
JavaEdge
2021/10/18
1.3K0
什么是覆盖索引_数据库为什么一定要覆盖索引
在了解覆盖索引之前我们先大概了解一下什么是聚集索引(主键索引)和辅助索引(二级索引)
全栈程序员站长
2022/09/27
5070
什么是覆盖索引_数据库为什么一定要覆盖索引
图解 MySQL 索引,清晰易懂,写得太好了!
作者:shuaibing90 来源:www.xysycx.cn/articles/2020/12/05/1607146183637.html
Java技术栈
2021/11/12
7310
MySQL索引下推:提升数据库性能的关键优化技术
👋 你好,我是 Lorin 洛林,一位 Java 后端技术开发者!座右铭:Technology has the power to make the world a better place.
Lorin 洛林
2023/11/21
4400
MySQL索引下推:提升数据库性能的关键优化技术
如何添加合适的索引:MySql 数据库索引认知
99%的焦虑都来自于虚度时间和没有好好做事,所以唯一的解决办法就是行动起来,认真做完事情,战胜焦虑,战胜那些心里空荡荡的时刻,而不是选择逃避。不要站在原地想象困难,行动永远是改变现状的最佳方式
山河已无恙
2025/02/25
4650
如何添加合适的索引:MySql 数据库索引认知
要想通过面试,MySQL的Limit子句底层原理你不可不知
  在二级索引idx_key1中,key1列是有序的,查找按key1列排序的第1条记录,MySQL只需要从idx_key1中获取到第一条二级索引记录,然后直接回表取得完整的记录即可,这个很容易理解。
砖业洋__
2023/05/06
5110
要想通过面试,MySQL的Limit子句底层原理你不可不知
数据库设计规范
数据库的重要性不言而喻。对程序员来说跟数据库打交道更是家常便饭。数据库给开发带来了巨大的便利。我们或多或少的知道一些数据库设计规范,但并不全面。今天我就简单整理一下,帮自己做个总结梳理,也希望可以帮到小伙伴们。
全栈程序员站长
2022/09/14
1.6K0
第06章_索引的数据结构
🧑个人简介:大家好,我是 shark-Gao,一个想要与大家共同进步的男人😉😉
程序员Leo
2023/08/02
2210
第06章_索引的数据结构
MySQL 语句优化 ICP
Index Condition Pushdown(ICP)是MySQL 5.6中的的新特性,是一种在存储引擎层使用索引过滤数据的一种优化方式。ICP可以减少存储引擎访问基表的次数以及MySQL服务器访问存储引擎的次数。
数据和云
2021/08/27
1.8K0
MySQL 语句优化 ICP
数据库-面试
共享锁也称为读锁,相互不阻塞,多个客户在同一时刻可以同时读取同一个资源而不相互干扰。
知识浅谈
2022/02/25
1.1K0
MySQL 覆盖索引与延迟关联
本期来谈谈覆盖索引与延迟关联。在此之前,我们先简单建立一个订单表 Orders 用于举例说明。表中共包含 3 个字段:
江不知
2020/09/08
1.7K0
MySQL 覆盖索引与延迟关联
推荐阅读
相关推荐
掌握高性能SQL的34个秘诀🚀多维度优化与全方位指南
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档