MySQL千万级数据优化方案

news2025/1/11 0:52:11

简介

                          ↓↓↓处理千万级数据的MySQL数据库,可以采取以下优化措施↓↓↓

                                                         

  1. 使用索引:确保对经常用于查询和排序的字段添加索引。不要在查询中使用SELECT *,而是明确指定需要的字段。
  2. 分区表:如果表中的数据按照时间或其他维度进行划分,可以考虑使用分区表。这有助于加快查询速度,因为MySQL可以只扫描一部分数据。
  3. 缓存:考虑使用缓存,如Redis,来存储经常查询的数据。这可以减轻数据库的负担,提高查询速度。
  4. 水平扩展:增加MySQL服务器的数量来提高处理能力。可以使用负载均衡技术将请求分配到不同的服务器上。
  5. 优化查询语句:确保查询语句简单、高效。避免使用子查询和复杂的JOIN语句。对查询结果进行分页,以减少返回的数据量。
  6. 数据库监控:定期监控数据库的性能指标,如慢查询日志、锁等待等。根据监控结果对数据库进行调优,如调整缓存大小、优化索引等。
  7. 使用索引优化器:使用MySQL自带的索引优化器来分析查询性能,并找出可以优化的字段和索引。
  8. 数据库分区:根据业务逻辑对数据库进行分区,将相关数据存储在同一个分区中。这有助于加快查询速度,减少锁等待等问题。
  9. 优化MySQL配置:根据硬件和业务需求,对MySQL的配置进行优化,如调整缓冲区大小、连接数等。

1、创建数据 

1.1、建表语句

DROP TABLE IF EXISTS `user_data`;
CREATE TABLE `user_data`  (
   `id` bigint(50) NOT NULL AUTO_INCREMENT,
   `attr1` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
   `attr2` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
   `attr3` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
   `attr4` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
   `attr5` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
   `attr6` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
   `attr7` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
   `attr8` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
   `attr9` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
   `attr10` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
   `attr11` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
   `attr12` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
   PRIMARY KEY (`id`) USING BTREE
 ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;

1.2、存储过程(反例)

存储过程实现效率低(不推荐 仅供参考)

CREATE DEFINER=`root`@`localhost` PROCEDURE `P_xiao_jian`()
BEGIN
DECLARE i INT DEFAULT 1;
	#Routine body goes here...
	WHILE i<=10000000 DO
        INSERT INTO user_data(id,attr1) VALUES(i,'CSDN臭弟弟测试数据');
        
        SET i = i+1;
    END WHILE;

END

 可以看到效率很慢,执行老好长时间才14万条数据

 

1.3、高效执行(正例)

代码实现更高效(大约30多秒,推荐)

import com.baomidou.mybatisplus.core.toolkit.IdWorker;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

public class TestDataController {

    /**
     *  快速添加一千万条测试数据
     * @param args
     */
    public  static void main(String[] args){

        String sql = "INSERT INTO user_data(id,attr1) VALUES(%s,'CSDN臭弟弟测试数据');";
        System.out.println(String.format(sql, IdWorker.getId()));
        String path="J:\\testData.sql";
        File file=new File(path);
        if(!file.exists()){
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        try {
            //BufferedOutputStream是Java中一个用于输出字节流的缓冲区类。
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(path)) ;
            long startTime = System.currentTimeMillis();
            for (int i = 0; i < 10000000; i++) {
                //写数据  IdWorker是一个Java类,该方法返回一个long类型的ID。
                bos.write(String.format(sql, IdWorker.getId()).getBytes());
                if(i<10000000-1){
                    bos.write("\n".getBytes());
                }
            }

            long endTime = System.currentTimeMillis();
            System.out.println("一千万条测试数据耗时:" + (endTime - startTime));

            //释放资源
            bos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

查看testData.sql 文件

1.4、使用Navicat将sql文件导入数据库

导入testData.sql 文件(注:导入之前如果testData.sql文件生成随机id ,导入前关闭主键自增),当然也可以命令行导入。

导入完成 

 

查询一千万条测试数据 耗时8秒

 

 

 1.5、普通分页查询

注意: MySQL 是通过 LIMIT 语句来选取指定的条数, Oracle 使用 ROWNUM 来选取指定的条数。

MySQL:

  • LIMIT子句用于限制结果集中返回的行数,语法如下↓↓↓
SELECT attr1, attr2, ...  
FROM table1
LIMIT offset, count;

    说明: 

    offset是起始行数(也称之为偏移量),count是要返回的行数。

  • 列如,选取表table1的前5条记录,可以使用以下语句↓↓↓
SELECT * FROM table1 LIMIT 0, 5;
  • 取从第3条记录开始的10条记录,可以使用以下语句↓↓↓
SELECT * FROM table1 LIMIT 3, 10;

Oracle:

  • ROWNUM是一个伪列,用于标识查询结果集中的每一行,从1开始,并在每一行中递增。语法如下↓↓↓
SELECT *  
FROM (  
  SELECT rownum rn, attr1, attr2, ...  
  FROM table  
)  
WHERE rn BETWEEN 10 AND 20;

说明: 

选取10到20行数据。查询结果将包括10行数据,从第11行到第20行。注意,必须先选取ROWNUM列,然后才能使用WHERE子句来限制结果集。

2、开始测试查询

注意: 最近看到平台很多这样的帖子复现给大家,都在说这个偏移量 数据量 ,数据越来越大肯定是影响查询效率啊,查一条数据 和查100万条数据 能一样吗? 以此叠加数据效率肯定是越来越慢。

2.1、测试语句

SELECT * FROM user_data LIMIT 10000, 10;
  •  查询结果(两次结果 分别是: 0.039s /0.033s)秒级的够可以吧! 毕竟是本地也正常 。 继续↓↓↓

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

语句:

SELECT * FROM user_data LIMIT 10000, 10;
SELECT * FROM user_data LIMIT 10000, 100;
SELECT * FROM user_data LIMIT 10000, 1000;
SELECT * FROM user_data LIMIT 10000, 10000;
SELECT * FROM user_data LIMIT 10000, 100000;
SELECT * FROM user_data LIMIT 10000, 1000000;

 执行结果:

 数据量越大执行时间越长,往下继续↓↓↓(为什么不在加大数据测试,我不敢,电脑会卡)

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

语句:

SELECT * FROM user_data LIMIT 10, 10000;
SELECT * FROM user_data LIMIT 100, 10000;
SELECT * FROM user_data LIMIT 1000, 10000;
SELECT * FROM user_data LIMIT 10000, 10000;
SELECT * FROM user_data LIMIT 100000, 10000;
SELECT * FROM user_data LIMIT 1000000, 10000;

 执行结果:

 偏移量越大执行时间越长,往下继续↓↓↓

3、优化查询

3.1 数据量过大问题

语句:

SELECT * FROM user_data LIMIT 1, 1000000;
SELECT id FROM user_data LIMIT 1, 1000000;
SELECT id, attr1, attr2, attr3, attr4, attr5, attr6, attr7, attr8, attr9, attr10, attr11, attr12 FROM user_data LIMIT 1, 1000000;

执行结果:

 说明: 我相信没有人会这么干的吧!  查几十万的数据,当然这种情况也不能排查,就算有也会使用 redis数据库做缓存处理 ,redis是一个高速缓存服务器,可以快速地存储和检索数据。redis读取速度达到10万/s ,写的速度为8万/秒。

  • 注意代码中涉及查询的sql禁止select *
  • 严谨使用 SELECT * 会出现性能问题,使用星号会读取所有字段,增加开销。
  • 建议在使用SELECT语句时,不要使用星号,而是明确指定需要查询的字段。
  • 字段数不同问题:如果你在使用"insert into table1 select * from table2"这样的语句时,若table1和table2的字段数不同,会导致任务运行失败出现错误。

3.2 偏移量过大问题

3.2.1 采用子查询方式

语句:

SELECT id FROM user_data LIMIT 1000000, 1;
SELECT * FROM user_data WHERE id >= (SELECT id FROM user_data LIMIT 1000000, 1) LIMIT 10;

 说明: 定位偏移位置的 id,再查询数据↓↓↓

执行结果:

 说明: 接下来分析查看EXPLAIN执行计划↓↓↓

3.2.2 EXPLAIN分析sql 执行计划

语句:

EXPLAIN SELECT id FROM user_data LIMIT 1000000, 1;
EXPLAIN SELECT * FROM user_data WHERE id >= (SELECT id FROM user_data LIMIT 1000000, 1) LIMIT 10;

执行结果:

 

 上面执行计划走索引了啊???  继续↓↓↓

3.2.3 加索引

没有在加一层解决不了的 ,在加索引。(UNIQUE  唯一索引)

Navicat视图工具加索引,也可以通过命令。

执行语句:

EXPLAIN SELECT id FROM user_data LIMIT 1000000, 1;
EXPLAIN SELECT * FROM user_data WHERE id >= (SELECT id FROM user_data LIMIT 1000000, 1) LIMIT 10;

执行结果: 

 在和之前对比有比较显著的提高

再次分析执行计划:

 

总结: 命中的索引不一同,命中唯一索引的查询效率更高。

  • 索引优化:在表中添加适当的索引可以提高查询性能,尤其是对于关联查询。确保在建立索引时考虑到查询条件,并避免重复索引
  • 索引并不是越多越好,要根据查询有针对性的创建,考虑在WHEREORDER BY命令上涉及的列建立索引,可根据EXPLAIN来查看是否用了索引还是全表扫描

 

3.2.1、重点头戏来了(子查询优化带来的问题)

子查询优化带来的问题,加点条件 你猜性能还会好吗? 继续↓↓↓

SELECT *  FROM user_data 
WHERE id >= ( SELECT id FROM user_data ORDER BY id desc LIMIT 1000000, 1 ) 
ORDER BY id LIMIT 10;

执行结果:

 

来查看执行计划:

虽然走索引了但是都彪到1.6秒,在加点复杂查询会更高,回到最开始的简介部分。

第5条优化查询语句:确保查询语句简单、高效。避免使用子查询和复杂的JOIN语句。对查询结果进行分页,以减少返回的数据量。 

总结: 如果设计初期能够预料到数据库表的数据会倍增长,请合理的构建优化方案,比如: 索引、分区表、缓存、水平扩展、数据库分区、优化MySQL配置  等等....

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

26岁机电专业,零基础转行学云计算,求推荐靠谱机构!

26岁机电专业&#xff0c;零基础转行学云计算&#xff0c;求推荐靠谱机构&#xff01; 关于26岁零基础转行云计算&#xff0c;求机构推荐这类问题。建议可以先把自己的具体需求整理清楚&#xff0c;例如自身的学习能力情况、需要学习的专业的技术内容、你想要通过培训学习达到什…

承接vue2->vue3的一些变动

1.Vue3简介 2020年9月18日&#xff0c;Vue.js发布3.0版本&#xff0c;代号&#xff1a;One Piece&#xff08;海贼王&#xff09;耗时2年多、2600次提交、30个RFC、600次PR、99位贡献者github上的tags地址&#xff1a;https://github.com/vuejs/vue-next/releases/tag/v3.0.0 …

NetApp FAS 混合闪存阵列协助您建构简单易用、聪明智慧、值得信赖的储存基础架构

NetApp FAS 混合闪存阵列 主要优势 1、简单易用&#xff1a;节省您宝贵的时间、金钱和人力 •几分钟内完成储存资源配置。 •以获证实的效率技术降低成本。 •可在单一系统上管理档案与区块资料。 2、聪明智慧&#xff1a;灵活因应瞬息万变的业务需求 •以不中断营运的方式扩…

javascript中的错误类型

javascript 中的错误类型&#xff1a; SyntaxErrorTypeErrorReferenceErrorRangeErrorURLErrorError SyntaxError 语法错误 // 当您在编写一个函数时忘记了括号 ,)来括起您的代码&#xff0c;您将收到一个SyntaxError错误 function say(text) {return text; }say(shark;// …

[论文阅读72]Parameter-Efficient Transfer Learning for NLP

1. 基本信息 题目论文作者与单位来源年份Parameter-Efficient Transfer Learning for NLPNeil Houlsby等Google Research&#xff0c;雅盖隆大学-波兰PMLR2019 Houlsby N, Giurgiu A, Jastrzebski S, et al. Parameter-efficient transfer learning for NLP[C]//Internationa…

代码随想录训练营Day49| 121. 买卖股票的最佳时机 122.买卖股票的最佳时机II

目录 学习目标 学习内容 121. 买卖股票的最佳时机 122.买卖股票的最佳时机II 学习目标 121. 买卖股票的最佳时机 122.买卖股票的最佳时机II 学习内容 121. 买卖股票的最佳时机 121. 买卖股票的最佳时机 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/prob…

chatgpt赋能Python-python_ip地址转换

Python IP地址转换&#xff1a;原理、常用函数和示例 在网络编程中&#xff0c;IP地址是一个很重要的概念。Python提供了很多IP地址转换函数&#xff0c;这篇文章将讲解其原理、常用函数和示例。 IP地址转换原理 IP地址是由32位表示的二进制数&#xff0c;它是计算机在网络上…

socket概述 python中如何使用TCP/UDP协议实现通信-教程

很多编程语言中&#xff0c;都使用scoket套接字实现网络通信。 Socket是对TCP/IP协议的封装&#xff0c;Socket本身就是一个调用接口&#xff08;API&#xff09;&#xff0c;方便程序员用Socket使用TCP/IP协议簇&#xff0c;实现网络通信。 不同编程语言&#xff0c;shiyong…

基于ROS2的costmap中Obstacle Layer中对障碍物信息的增加与删除机制的方案调研。

文章目录 1.背景2.目标3. 障碍物信息添加方式发送数据的数据结构与接收数据的数据结构 4. 障碍物清理机制4.1 可调参数4.2 优化光追算法4.3 障碍物跟踪 1.背景 基于costmap地图&#xff0c;使用navigation导航时&#xff0c;会出现由于激光雷达/图像测距的局限性&#xff0c; …

RocketMQ 在小米的多场景灾备实践案例

作者&#xff1a;邓志文、王帆 01 为什么要容灾&#xff1f; 在小米内部&#xff0c;我们使用 RocketMQ 来为各种在线业务提供消息队列服务&#xff0c;比如商城订单、短信通知甚至用来收集 IoT 设备的上报数据&#xff0c;可以说 RocketMQ 的可用性就是这些在线服务的生命线…

我写了个操作系统,却被别人给骂了!

前言 哈喽&#xff0c;小伙伴们好&#xff0c;我是子牙。是一个擅长深入研究Windows内核、Linux内核、Hotspot源码的资深程序员&#xff0c;之前是JVM专家&#xff0c;手写过JVM。所以做老师后&#xff0c;第一个打造的课程便是《手写JVM》小班&#xff0c; 一经推出就受到了学…

我的苹果手机的越狱之旅

最近因为业务需要&#xff0c;需要一台越狱手机&#xff1b;就把测试机6plus拿来做越狱使用&#xff0c;在此之前先大致说明一下越狱的原理、应用、流程以及可能存在的问题&#xff1a; 越狱是指通过一些技术手段&#xff0c;使iOS设备可以访问到iOS系统的全部控制权&#xff0…

抛弃Vuex,使用Pinia

Pinia 符合直觉的 Vue.js 状态管理库 文章目录 Pinia 符合直觉的 Vue.js 状态管理库1.简介2.为什么要使用Pinia3.安装3.1 挂载pinia 4.创建一个store容器4.1 Option 参数4.2 Setup 参数 5.三个重要概念5.1 State5.2 Getter**5.3 Action** 6.购物车实例6.1 商品列表组件 1.简介 …

【Python-Django】如何在一个项目中创建多个app模块

django开发案例&#xff1a;a​​​​​【Django】开发日报_1_Day&#xff1a;用户管理系统案例-创建项目_django 开发用户管理系统_代码骑士的博客-CSDN博客 前面做过的管理系统项目功能比较单一&#xff0c;只用一个模块就能解决问题。如果想创建多个不同的模块的话&#xf…

Nodejs之HTTP模块

目录 前言一&#xff0c;创建HTTP模块1.1 基本使用1.2 注意事项 二&#xff0c;查看报文2.1 浏览器查看HTTP报文2.2 利用request获取HTTP请求报文2.2.1 获取请求行和请求头 2.2.2 获取请求路径2.2.3 获取查询字符串 三&#xff0c;跟请求报文相关的练习四&#xff0c;设置响应报…

聊天机器人开发实战--(微信小程序+SpringCloud+Pytorch+Flask)【完整版】

文章目录 前言架构小程序端管理端运维端 交互聊天页面聊天发送流程历史聊天记录个人中心 总结 前言 没想到从五一之后&#xff0c;到现在鸽了那么久。没办法&#xff0c;实话实说&#xff0c;确实忙&#xff0c;五一期间就没怎么休息&#xff0c;开局第一周&#xff0c;准备IE…

Scala学习(七)---面向对象特质

文章目录 1.面向对象特质(Trait)2.特质声明2.1 特质的特点2.2 特质冲突2.3 特质叠加2.4 特质自身类型2.5 特质和抽象类的区别扩展 1.面向对象特质(Trait) 在Scala语言中&#xff0c;采用特质trait(特征)来代替接口的概念&#xff0c;也就是说&#xff0c;多个类具有相同的特质…

分享7款优质免费的Figma“中文插件”

今天我要向你们分享一些 Figma 的“中文插件”&#xff0c;这些插件不仅功能强大&#xff0c;而且免费使用&#xff0c;非常方便&#xff0c;而且是完全中文的页面使用起来非常便捷&#xff0c;可以大大提高设计师的效率和体验。 1、「平面 3D」 插件 首先是平面 3D 插件。该…

OpenVINO 2022.3之九:Post-training Optimization Tool (POT)

OpenVINO 2022.3之九&#xff1a;Post-training Optimization Tool (POT) Post-training Optimization Tool (POT) 通过在已训练好的模型上应用量化算法&#xff0c;将模型的权重和激活函数从 FP32/FP16 的值域映射到 INT8 的值域中&#xff0c;从而实现模型压缩&#xff0c;以…