深入解析:MySQL进阶知识点(八)---- SQL优化

news/2025/10/27 1:03:53/文章来源:https://www.cnblogs.com/yangykaifa/p/19167690

一、 插入数据优化

当需要插入大量数据时,普通的单条INSERT语句效率极低。

优化方案:

  1. 批量插入

    -- 不推荐:多次网络I/O和事务开销
    INSERT INTO table VALUES (1, 'a');
    INSERT INTO table VALUES (2, 'b');
    -- 推荐:一次插入多条数据
    INSERT INTO table VALUES (1, 'a'), (2, 'b'), (3, 'c');
  2. 手动提交事务

    -- 避免每条INSERT都自动提交事务
    START TRANSACTION;
    INSERT INTO table VALUES (1, 'a');
    INSERT INTO table VALUES (2, 'b');
    COMMIT;
  3. 主键顺序插入
    按主键的顺序插入数据,性能高于乱序插入。

  4. 使用LOAD指令
    对于海量数据插入,可以使用MySQL的LOAD命令从文件加载。

    -- 从本地文件加载数据
    LOAD DATA LOCAL INFILE '/path/to/file.csv'
    INTO TABLE table_name
    FIELDS TERMINATED BY ','
    LINES TERMINATED BY '\n';

二、 主键优化

  1. InnoDB的数据组织方式

    • InnoDB使用B+Tree索引组织数据

    • 所有数据都存储在聚簇索引的叶子节点

  2. 页分裂与页合并

    • 页分裂:当页已满,新插入的数据会导致页分裂,影响性能

    • 页合并:当页中数据删除达到阈值(MERGE_THRESHOLD,默认50%),InnoDB会寻找相邻页合并

  3. 主键设计原则

    • 尽量短:二级索引叶子节点存储主键,主键过长会占用更多空间

    • 顺序插入:使用AUTO_INCREMENT或雪花算法等,避免随机主键

    • 避免频繁更新:主键更新会导致二级索引同步更新

三、 ORDER BY优化

  1. Using filesort的情况

    • 通过磁盘文件或内存进行排序,效率较低

    • 在EXPLAIN的Extra字段中显示Using filesort

  2. Using index的情况

    • 通过索引直接完成排序,效率高

    • 在EXPLAIN的Extra字段中显示Using index

  3. 优化方案:

    • 为ORDER BY的字段建立合适的索引

    • 遵循最左前缀法则

    • 多字段排序时,保持ORDER BY顺序与索引顺序一致

    • 避免SELECT *,减少回表操作

示例:

-- 索引: (age, salary)
-- 有效:使用索引排序
EXPLAIN SELECT id FROM employees ORDER BY age, salary;
-- 无效:出现Using filesort
EXPLAIN SELECT id FROM employees ORDER BY salary, age;

四、 GROUP BY优化

  1. Using temporary的情况

    • 使用临时表进行分组,效率较低

    • 在EXPLAIN的Extra字段中显示Using temporary

  2. 优化方案:

    • 为GROUP BY字段建立索引

    • 在GROUP BY后使用ORDER BY NULL取消排序(如不需要排序结果)

    • 遵循最左前缀法则

示例:

-- 索引: (dept_id)
-- 优化前:可能使用临时表
EXPLAIN SELECT dept_id, COUNT(*) FROM employees GROUP BY dept_id;
-- 优化后:使用索引,取消排序
EXPLAIN SELECT dept_id, COUNT(*) FROM employees GROUP BY dept_id ORDER BY NULL;

五、 LIMIT优化

在大数据量下,LIMIT分页的深分页问题:

-- 效率低:OFFSET越大越慢
SELECT * FROM table LIMIT 1000000, 10;

优化方案:

  1. 覆盖索引 + 子查询

    SELECT * FROM table t
    JOIN (SELECT id FROM table ORDER BY id LIMIT 1000000, 10) tmp
    ON t.id = tmp.id;
  2. 基于上次位置的查询(游标分页)

    -- 传统分页
    SELECT * FROM table ORDER BY id LIMIT 20;
    -- 下一页(记录上次的最大id)
    SELECT * FROM table WHERE id > 上次的最大id ORDER BY id LIMIT 20;

六、 COUNT优化

  1. COUNT的几种用法

    • COUNT(主键):InnoDB遍历整表,把主键值取出,按行累加

    • COUNT(字段):统计该字段不为NULL的数量

    • COUNT(1):InnoDB遍历整表,但不取值,按行累加

    • COUNT(*):MySQL做了优化,不取值,按行累加

  2. 效率对比
    COUNT(*) ≈ COUNT(1) > COUNT(主键) > COUNT(字段)

  3. 优化方案:

    • 使用COUNT(*),MySQL会自行优化

    • 维护计数表,实时更新总数

    • 使用Redis等外部缓存记录总数

七、 UPDATE优化

核心原则: 避免表锁,使用行锁。

  1. InnoDB的行锁

    • 基于索引加行锁

    • 不基于索引加表锁

  2. 优化方案:

    -- 索引: (id)
    -- 高效:使用行锁
    UPDATE table SET name = 'new' WHERE id = 1;
    -- 危险:无索引,使用表锁,阻塞其他操作
    UPDATE table SET name = 'new' WHERE name = 'old';
  3. 最佳实践

    • 确保WHERE条件使用索引

    • 避免在事务中执行大量UPDATE

    • 分批更新大数据量

优化总结表格

优化场景核心问题优化方案
插入数据单条插入效率低批量插入、手动事务、LOAD DATA
主键设计页分裂、空间占用短主键、顺序插入、避免更新
ORDER BYUsing filesort创建合适索引、遵循最左前缀
GROUP BYUsing temporary创建索引、ORDER BY NULL取消排序
LIMIT深分页性能差覆盖索引+子查询、游标分页
COUNT全表扫描效率低使用COUNT(*)、维护计数表
UPDATE表锁阻塞WHERE条件必须使用索引

通用优化建议

  1. 善用EXPLAIN:分析SQL执行计划是优化的第一步

  2. 索引是双刃剑:合理创建,避免过多

  3. **避免SELECT ***:只查询需要的字段

  4. 大数据量操作:分批处理,避免大事务

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

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

相关文章

102302106-陈昭颖-第一次作业

作业一 作业①: 1.爬取大学排名 要求:用requests和BeautifulSoup库方法定向爬取给定网址(http://www.shanghairanking.cn/rankings/bcur/2020 )的数据,屏幕打印爬取的大学排名信息。 输出信息:排名 学校名称 省市…

详细介绍:Claude Sonnet 4.5:一次面向落地的常规升级(性能、安全、开发者工具)

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

国庆集训day1~2笔记-动态规划

国庆集训 Day 1~2 笔记 - 动态规划 DP 时间复杂度计算:状态数 $\times$ 决策数 $\times$ 转移代价 序列型 DP 最长上升子序列 B3637 最长上升子序列 - 洛谷$O(n^2)$ 解法:$f_i = \max{f_j + 1}$,其中 $a_j < a_i…

P1679 神奇的四次方数

P1679 神奇的四次方数 题目链接:P1679 神奇的四次方数 - 洛谷 题目描述 将一个整数 $m$ 分解为 $n$ 个四次方数的和的形式,要求 $n$ 最小。例如,当 $m = 706$ 时,因为 $706 = 5^4 + 3^4$,所以有 $n = 2$。可以证明…

P1877 [HAOI2012] 音量调节

P1877 [HAOI2012] 音量调节 [题目链接:P1877 HAOI2012] 音量调节 - 洛谷 题目描述 一个吉他手准备参加一场演出。他不喜欢在演出时始终使用同一个音量,所以他决定每一首歌之前都需要改变一次音量。在演出开始之前,他…

数论导论

数论导论 快速幂 求 $a^b\bmod p$ 的结果。 我们可以构造如下算法: $ab=\begin{cases}(a)^2 &\texttt{b is even}\a(a{\frac{b-1}2})2&\texttt{b is odd}\end{cases}$ 每次 $b$ 会减半,所以时间复杂度 $O(\l…

P14321 「ALFR Round 11」D Adjacent Lifting, Fewest Rounds 题解

前言:考场上使用神秘的样例分析法蒙出来了,赛后发现竟然被评了个紫,万恶的良心驱使我写一篇题解。我们先看到操作。任选一个数字使其 \(+2\) 选择两个相邻的数字使其各 \(+1\)要求 使用操作 \(2\) 的次数最小。 换…

详细介绍:【Linux】进程的概念和状态

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

Minio外网访问内网上传的预签名url的方法以及报错原因

自己个人的经验总结: 当其他技术配置检查多次都无误,但就是不行的时候,要考虑低级错误的可能: 比如本次 就是 之前 存储桶 的名字改过,但是只改了代码里 获取预签名url的,上传的没有改 导致的结果就是url根本是错的,因…

【ESP32 在线语音】星火大模型

【ESP32接入国产大模型之星火】https://blog.csdn.net/vor234/article/details/140594209

RT-Thread 之互斥量使用

互斥量(Mutex)是 RT-Thread 中用于解决线程间共享资源独占访问的核心 IPC 机制,本文简单介绍了互斥量的API函数和使用示例。一、互斥量概述 互斥量(Mutex)是 RT-Thread 中用于解决线程间共享资源独占访问的核心 I…

20232419 2025-2026-1 《网络与系统攻防技术》实验三实验报告

一、实验内容 1.1 了解恶意软件检测机制,学习免杀原理 1.2 熟悉msfvenom的使用,使用msfvenom中的编码器并尝试生成多种类型的文件 1.3 学习使用veil工具的使用 1.4 尝试进行压缩加壳和加密加壳 1.5 利用C语言shellco…

语义文本理解 BERT - MKT

语义文本理解 BERT 问题 如何区分一个同名的语义名字和物体? A区左边路口的房子 B区右边红绿灯的房子 两个房子含义是不一样的。 从“是什么”升级到“是什么以及在什么情境下”​​,提高了准确性。好的,这个问题…

详细介绍:分布式任务事务框架设计与实现方案

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

FM-Fusion 利用rgbd相机 ram-GroundingDINO-sam 重建语义地图 - MKT

FM-Fusion 利用rgbd相机 ram-GroundingDINO-sam 重建语义地图https://arxiv.org/pdf/2402.04555

AI元人文构想系列:从战略能力到价值对话的文明之路

AI元人文构想系列:从战略能力到价值对话的文明之路引言:超越“鹦鹉”与“黑洞”的AI未来 当前人工智能的发展正站在一个十字路口:一边是精于模仿却回避价值矛盾的“鹦鹉AI”,另一边是潜藏于金融、信息和地缘政治领…

Rig 项目深度分析报告

Rig 项目深度分析报告 基于我对这个项目的深入研究,让我为你详细分析 Rig 这个 Rust LLM 框架。 📋 项目概述 Rig 是由 Playgrounds 开发的开源 Rust 库,专门用于构建可扩展、模块化且符合人体工程学的 LLM 驱动应…

事件日志查看Windows安装软件情况

在事件日志中选择应用程序日志筛选事件来源,事件ID号

RT-Thread之创建线程

使用RT-Thread创建线程的一些代码模板。一、静态线程创建 1、thread_task.c文件 #include "thread_task.h" #include "main.h" #include <stdio.h> #include "rtthread.h"/…

cias_voice_plyer_handle.c 解析

#if VOICE_PLAY_BY_UART /**************** * 播报器参数初始化 * * * * **/ void audio_player_param_init() {outside_init_stream(&mp3_player, &mp3_player_end, IOT_AUDIO_PLAY_BUF_SIZE);if (!mp3_…