MySQL亿级数据的查询优化-历史表该如何建

        前端时间在知乎上看到一个问题,今天有空整理并测试了一下:

        这个问题很具体,所以还是可以去尝试优化一下,我们基于InnoDB并使用自增主键来讲。

        比较简单的做法是将历史数据存放到另一个表中,与最近的数据分开。那是不是历史表随便建就行了?其实这里的区别很大:       

         先讲一下优化思路:如果数据量太大(远远超过内存),对于批量查询来说单纯的添加索引作用不大,需要将数据按照查询重新组织降低查询需要的IO次数。

        首先拿一组数据来分析一下,如果采用自增ID,数据按写入顺序存储在磁盘上,数据在磁盘上的分布情况大体如下:

        如果把用户1的所有数据都查询出来,并且这些数据页都不在内存的情况下,需要执行3次IO。

        但是,只要将数据整理一下,同一个用户的数据顺序存放,即数据的组织方式如下:

查询用户1的所有数据,并且这些数据页都不在内存的情况下,只需要执行1次IO即可。

在这个场景中,通常一次读取几百条到上千条积分变化数据,性能差异还是非常明显的。

现在的问题是:怎么让数据的组织是顺序的?其实很简单,只需要在转储时将一个用户的所有数据一起转储(也就是相邻写入,这样他们存储在磁盘上也是相邻的)。

附:这里我们设计一个场景分别测试一下这两种情况的性能差别。

使用下面的语句创建两个表:

CREATE TABLE t_score_log_1
(`id` bigint AUTO_INCREMENT,`user_id` int,`score` int,`log_time` datetime,PRIMARY KEY(`id`),KEY `idx_user_id`(`user_id`)
);CREATE TABLE t_score_log_2
(`id` bigint AUTO_INCREMENT,`user_id` int,`score` int,`log_time` datetime,PRIMARY KEY(`id`),KEY `idx_user_id`(`user_id`)
) ;

然后,创建两个存储过程用于向两个表中插入数据:

DELIMITER $
CREATE PROCEDURE insert_proc_1()
BEGINDECLARE i INT DEFAULT 0;DECLARE uid INT DEFAULT 0;WHILE i < 1000DOSET uid = 1;WHILE uid < 100001DOINSERT INTO t_score_log_1(`user_id`,`score`,`log_time`) VALUES(uid,  i % 100, DATE_ADD('2023-1-1',interval i second));SET uid = uid + 1;IF uid % 1000 = 0 THENCOMMIT;END IF;END WHILE;SET i = i + 1;COMMIT;END WHILE;
END $
DELIMITER ;DELIMITER $
CREATE PROCEDURE insert_proc_2()
BEGINDECLARE i INT DEFAULT 0;DECLARE uid INT DEFAULT 1;WHILE uid < 100001DOSET i = 0;WHILE i < 1000DOINSERT INTO t_score_log_2(`user_id`,`score`,`log_time`) VALUES(uid,  i % 100, DATE_ADD('2023-1-1',interval i second));SET i = i + 1;END WHILE;SET uid = uid + 1;COMMIT;END WHILE;
END $
DELIMITER ;

接着,调用这两个函数向两个表中写入数据:

call insert_proc_1();call insert_proc_2();

注意:为了更快的插入数据,关闭mysql的binlog并设置innodb_flush_log_at_trx_commit为0。

***************等待中****************

终于,数据插入完成,随机查询一些用户的历史数据比较一下耗时:

可以看到针对整理过后的数据(也就是表:t_score_log_2)查询性能远远高于未整理的表。

所以,针对历史数据特别大的场景,适当调整数据的分布情况可以极大的提升查询性能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/450429.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

参考数据集INRIA Holidays dataset

Download datasets 很贴心,MATLAB访问代码: % This function reads a siftgeo binary file % % Usage: [v, meta] = siftgeo_read (filename, maxdes) % filename the input filename % maxdes maximum number of descriptors to be loaded % (default=unlimit…

java05 数组

一 概念介绍 指的是一种容器&#xff0c;可以同来存储同种数据类型的多个值。 但是数组容器在存储数据的时候&#xff0c;需要结合隐式转换考虑。 比如&#xff1a; 定义了一个int类型的数组。那么boolean。double类型的数据是不能存到这个数组中的&#xff0c; 但是byte类…

1895_分离进程的能力

1895_分离进程的能力 全部学习汇总&#xff1a; g_unix: UNIX系统学习笔记 (gitee.com) 有些理念可能在控制类的嵌入式系统中不好实施&#xff0c;尤其是没有unix这样的系统搭载的情况下。如果是考虑在RTOS的基础上看是否有一些理念可以做尝试&#xff0c;我觉得还是可以有一定…

绝世唐门:霍挂六个十万年魂环,一穿七灭团再现,淘汰赛顺利晋级

Hello,小伙伴们&#xff0c;我是拾荒君。 国漫《斗罗大陆2绝世唐门》第32期超前爆料&#xff0c;霍雨浩开局便释放六个十万年魂环&#xff0c;以绝对的气场碾压天灵学院代表队。首次参与高级魂师大赛&#xff0c;霍雨浩便大放异彩秀出超级霍挂&#xff0c;此等操作就连当初的唐…

[Python] scikit-learn中数据集模块介绍和使用案例

sklearn.datasets模块介绍 在scikit-learn中&#xff0c;可以使用sklearn.datasets模块中的函数来构建数据集。这个模块提供了用于加载和生成数据集的函数。 API Reference — scikit-learn 1.4.0 documentation 以下是一些常用的sklearn.datasets模块中的函数 load_iris() …

数字巨轮航行大数据海洋:数据可视化引领时代潮流

在大数据时代的潮流中&#xff0c;数据可视化如同一艘畅行无阻的科技巨轮&#xff0c;引领我们穿越数字浩瀚的大海&#xff0c;使我们在信息的航程中游刃有余。下面我就从可视化从业者的角度&#xff0c;来简单说说数据可视化是如何帮助我们在大数据时代畅行无阻的。 数据可视化…

1、安全开发-Python爬虫EDUSRC目标FOFA资产Web爬虫解析库

用途&#xff1a;个人学习笔记&#xff0c;有所借鉴&#xff0c;欢迎指正 前言&#xff1a; 主要包含对requests库和Web爬虫解析库的使用&#xff0c;python爬虫自动化&#xff0c;批量信息收集 Python开发工具&#xff1a;PyCharm 2022.1 激活破解码_安装教程 (2022年8月25日…

CentOS 8 下载

https://mirrors.bfsu.edu.cn/centos/8-stream/isos/x86_64/ 下载地址&#xff1a; https://mirrors.bfsu.edu.cn/centos/8-stream/isos/x86_64/CentOS-Stream-8-x86_64-latest-dvd1.iso

【第二十二课】最短路:多源最短路floyd算法(acwing-852 spfa判断是否存在负环 / acwing-854 / c++代码)

目录 acwing-852 代码如下 一些解释 acwing-854 foyld算法思想 代码如下 一些解释 acwing-852 在spfa求最短路的算法基础上进行修改。 代码如下 #include<iostream> #include<cstring> #include<algorithm> #include<queue> using names…

适用于 Windows 7/8/10/11电脑的 12 款顶级数据恢复软件

很多时候&#xff0c;我们在 Windows 7 /8/10/11下不小心按了删除键&#xff0c;从而丢失了硬盘或 USB 驱动器中的重要文件和数据。在某些情况下&#xff0c;病毒或软件错误可能会损坏您的硬盘&#xff0c;从而影响您的文件。在这种情况下&#xff0c;您迫切需要一款适用于 Win…

坚持刷题|二叉树的前、中、后序遍历(递归迭代)

文章目录 题目思考递归实现迭代实现前序遍历后序遍历中序遍历 在前、中、后序的迭代遍历中&#xff0c;为什么都采用栈来模拟递归&#xff0c;而非队列&#xff1f; Hello&#xff0c;大家好&#xff0c;我是阿月。坚持刷题&#xff0c;老年痴呆追不上我&#xff0c;今天刷&…

030 可变参数

可变参数定义 public static void main(String[] args) {// 多参数方式传递System.out.println(max(1,3,5,3,6,1,2));// 数组方式传递System.out.println(max(new int[]{1,3,5,3,6,1,2})); }static int max(int... nums){int max Integer.MIN_VALUE;for (int num : nums) {if(…