【Mysql】我在广州学Mysql 系列——Mysql 性能优化

ℹ️大家好,我是练小杰,今天又是美好的星期一了,新的工作又要开始了,努力!!奋斗!!😆


本文是针对Mysql 性能优化知识进行学习与讨论,后续将添加更多相关知识噢,谢谢各位的支持🙏

前情回顾: 【Mysql 日志管理详解

数据库专栏:👉【数据库专栏】【Mysql练习题

主页:👉【练小杰的CSDN

申公豹:"人心中的成见是一座大山"

性能优化

理解性能优化

  • 优化MySQL数据库是数据库管理员和数据库开发人员的必备技能。
  • 通过合理的数据库设计、索引优化、查询优化、缓存优化、表结构优化、硬件和配置优化以及其他优化方法,可以显著提高 MySQL 数据库的性能,确保其在高负载和高并发环境下的稳定性和高效性。

MySQL优化的作用:

一方面是找出系统的瓶颈,提高MySQL数据库整体的性能;另一方面,需要合理的结构设计和参数调整,以提高用户操作响应的速度;同时还要尽可能的节省系统资源,以便系统可以提供更大负荷的服务。

优化查询

索引对查询速度的影响

MySQL中提高性能的一个最有效的方式就是对数据表设计合理的索引

索引提供了高效访问数据的方法,并且可以加快查询的速度,因此,索引对查询的速度有着至关重要的影响。

sql 复制代码
-- 创建索引
CREATE INDEX idx_name ON table_name(column_name);

-- 查看索引
SHOW INDEX FROM table_name;

-- 删除索引
DROP INDEX idx_name ON table_name;

分析查询语句

通过对查询语句的分析,可以了解查询语句执行情况,找出查询语句执行的瓶颈,从而优化查询语句。同时要避免全表扫描,确保查询条件使用索引。

  • 使用 EXPLAIN 分析查询语句
sql 复制代码
EXPLAIN SELECT * FROM table_name WHERE condition;
//或者使用DESCRIBE语句
DESCRIBE SELECT select_options

⚠️注意: 留意type 列(其中ALL 表示全表扫描,refrange 表示使用索引),以及 rows 列(扫描的行数越少越好)。

  • 避免 SELECT *,优化中为 只选择需要的列
sql 复制代码
SELECT column1, column2 FROM table_name;

使用索引查询

索引可以提高查询的速度。但并不是使用带有索引的字段查询时,索引都会起作用。

  • 使用LIKE关键字的查询语句

使用LIKE关键字进行模糊查询时,如果查询字段上有索引,索引会被利用,从而提高查询速度。如下,查询名字以"练"开头的所有用户。

sql 复制代码
SELECT * FROM users WHERE name LIKE '练%';
  • 使用多列索引的查询语句

多列索引(复合索引)是指在多个列上创建的索引。当查询条件涉及到这些列时,索引会被利用,从而提高查询的效率。如下,查询年龄在20到30岁之间且姓名为"练小杰"的用户。

sql 复制代码
SELECT * FROM users WHERE age BETWEEN 20 AND 30 AND name = '练小杰';

同时,为了优化上述查询,可以在 users 表上创建复合索引:

sql 复制代码
CREATE INDEX idx_age_name ON users (age, name);
  • 使用OR关键字的查询语句

OR关键字连接多个条件时,如果涉及的字段上有索引,索引会被利用,从而提高查询速度。如下,查询年龄为25岁或姓名为"eason"的用户。

sql 复制代码
SELECT * FROM users WHERE age = 25 OR name = 'eason';

优化子查询

  • 在MySQL中可以使用连接(JOIN)查询来替代子查询。
  • 连接查询不需要建立临时表,其速度比子查询要快,如果查询中使用到索引的话,性能会更好。连接之所以更有效率,是因为MySQL不需要在内存中创建临时表来完成查询工作。

表结构优化

选择合适的数据类型

使用最小的数据类型存储数据。例如,使用 TINYINT 代替 INT,使用 VARCHAR 代替 TEXT

规范化与反规范化

规范化: 减少数据冗余,提高数据一致性。

反规范化:合理地加入冗余数据减少连接操作,提高查询性能。

建立分区表

将大表分成多个小表,提高查询效率。

sql 复制代码
CREATE TABLE partitioned_table (
    id INT,
    created_at DATE
) PARTITION BY RANGE (YEAR(created_at)) (
    PARTITION p0 VALUES LESS THAN (2023),
    PARTITION p1 VALUES LESS THAN (2024),
    PARTITION p2 VALUES LESS THAN (2025)
);

分析表、检查表和优化表

  • MySQL提供了分析表、检查表和优化表的语句。
  1. 分析表:主要是分析关键字的分布。
  2. 检查表:主要是检查表是否存在错误。
  3. 优化表:主要是消除删除或者更新造成的空间浪费。

优化插入记录的速度

  • 影响插入速度的主要是索引、唯一性校验和一次插入记录条数等。根据这些情况,可以分别进行优化。

优化的方式:

  1. 禁用索引
  2. 禁用唯一性检查
  3. 使用批量插入
  4. 使用LOAD DATA INFILE 批量导入

配置优化

调整缓冲区大小

  • innodb_buffer_pool_size:InnoDB 缓冲池大小,建议设置为系统内存的 70%-80%。
sql 复制代码
SET GLOBAL innodb_buffer_pool_size = 1G;
  • key_buffer_sizeMyISAM 键缓冲区大小。
sql 复制代码
SET GLOBAL key_buffer_size = 512M;

调整连接数

  • max_connections:最大连接数。

    sql 复制代码
    SET GLOBAL max_connections = 500;
  • wait_timeout:连接空闲超时时间。

    sql 复制代码
    SET GLOBAL wait_timeout = 600;

启用查询缓存

  • query_cache_size:查询缓存大小。

    sql 复制代码
    SET GLOBAL query_cache_size = 64M;

利用日志与监控

慢查询日志

作用:记录执行时间超过指定阈值的查询。

sql 复制代码
-- 启用慢查询日志
SET GLOBAL slow_query_log = 'ON';

-- 设置慢查询阈值(单位:秒)
SET GLOBAL long_query_time = 2;

-- 查看慢查询日志路径
SHOW VARIABLES LIKE 'slow_query_log_file';

性能监控

  • SHOW STATUS:查看服务器状态。
sql 复制代码
 SHOW STATUS LIKE 'Threads_connected';
  • SHOW PROCESSLIST:查看当前连接和查询。
sql 复制代码
SHOW PROCESSLIST;

优化MySQL服务器

优化服务器硬件

服务器的硬件性能直接决定着MySQL数据库的性能。硬件的性能瓶颈,直接决定MySQL数据库的运行速度和效率。

  • 使用 SSD:因为 SSD 的读写速度远高于 HDD,适合高并发场景。

  • 增加内存: 增加内存可以提高缓冲区和缓存的效果。

  • 调整文件系统: 使用 XFSext4 文件系统,避免使用 ext3

优化MySQL的参数

通过优化MySQL的参数,可以提高资源利用率,从而达到提高MySQL服务器性能的目的。例如,下面的参数:

sql 复制代码
key_buffer_size、table_cache、query_cache_size
......

key_buffer_size 参数

  • MySQL 中用于索引块的缓冲区大小。它主要用于 MyISAM 存储引擎,但也会影响 InnoDB 存储引擎的性能。

  • 这个参数决定了 MySQL 用于缓存索引块的内存大小。较大的 key_buffer_size 可以存储更多的索引块,从而减少磁盘 I/O,提高查询性能。

  • 调整方法:我们可以通过以下命令查看和设置:

sql 复制代码
SHOW VARIABLES LIKE 'key_buffer_size';
SET GLOBAL key_buffer_size = 256M;

建议值:通常设置为服务器总内存的 25%30%,但具体值应根据实际工作负载进行调整。

table_cache 参数

  • table_cache(在 MySQL 5.1 及更高版本中称为 table_open_cache)是用于缓存打开的表文件的缓存大小。

  • 参数决定了 MySQL 可以缓存的打开表文件数量。较大的 table_cache 可以减少打开表文件时的磁盘 I/O,提高访问速度。同时,在高并发环境下,较大的表缓存可以提高并发处理能力,减少锁争用。

  • 配置建议:默认大小通常较小,建议根据服务器内存和并发连接数进行调整

sql 复制代码
SHOW VARIABLES LIKE 'table_open_cache';
SET GLOBAL table_open_cache = 1024;

建议值:通常设置为并发连接数的 10 倍左右,但具体值应根据实际工作负载进行调整。

query_cache_size 参数

  • query_cache_size 是 MySQL 用于缓存查询结果的缓冲区大小。
  • 参数决定了 MySQL 用于缓存查询结果的内存大小。对于相同的查询,MySQL 可以直接从缓存中返回结果,避免重复执行查询,提高查询速度。
  • 作用:对于频繁执行的相同查询,较大的查询缓存可以显著提高响应速度。
  • 调整方法:
sql 复制代码
SHOW VARIABLES LIKE 'query_cache_size';
SET GLOBAL query_cache_size = 128M;

建议值:通常设置为服务器总内存的 10% 到 20%,但具体值应根据实际查询负载进行调整。

应用示例

  • 假设有一台服务器,总内存为 8GB,可以考虑以下配置:
sql 复制代码
SET GLOBAL key_buffer_size = 2G;
SET GLOBAL table_open_cache = 2048;
SET GLOBAL query_cache_size = 1G;

高级优化

主从复制

作用:通过主从复制分担读负载。
sql 复制代码
-- 主服务器配置
SHOW MASTER STATUS;

-- 从服务器配置
CHANGE MASTER TO
    MASTER_HOST='master_host',
    MASTER_USER='replica_user',
    MASTER_PASSWORD='password',
    MASTER_LOG_FILE='mysql-bin.000001',
    MASTER_LOG_POS=107;

分库分表

作用:将大表分成多个小表,或将数据分布到多个数据库中。

工具:MyCAT分布式数据库中间件,以及ShardingSphere分库分表解决方案。

综合案例

步骤1:分析查询语句,理解索引对查询速度的影响

  1. 使用分析查询语句"SELECT * FROM fruits WHERE f_name='banana';",执行的语句及执行结果如下:
sql 复制代码
EXPLAIN SELECT * FROM fruits WHERE f_name='banana';
  • 结果说明

type: const 表示这是一个常量查询,查询速度非常快。
key: idx_f_name 表示使用了 idx_f_name 索引。
rows: 1 表示只扫描了一行数据。
Extra: Using index 表示使用了覆盖索引,查询效率高。

  1. 使用分析查询语句"SELECT * FROM fruits WHERE f_name like '%na'",执行的语句及执行结果如下:
sql 复制代码
EXPLAIN SELECT * FROM fruits WHERE f_name like '%na';
  • 结果说明

type: ALL 表示这是一个全表扫描,查询效率低。
key: NULL 表示没有使用索引。
rows: 1000 表示扫描了1000行数据(假设表中有1000行数据)
Extra: Using where 表示需要使用 WHERE 子句进行过滤

⚠️ 使用 LIKE '%na' 时,查询条件以通配符 % 开头,MySQL 无法使用索引进行优化。

  1. 使用EXPLAIN分析查询语句下面执行"SELECT * FROM fruits WHERE f_name like 'ba%';"语句如下:
sql 复制代码
EXPLAIN SELECT * FROM message WHERE title like ' ba%';
  • 结果说明

type: range 表示这是一个范围查询,查询效率较高。
key: idx_f_name 表示使用了 idx_f_name 索引。
rows: 50 表示扫描了50行数据(假设有50行数据符合条件)。
Extra: Using index 表示使用了覆盖索引,查询效率高。

步骤2:练习分析表、检查表、优化表

  1. 使用ANALYZE TABLE语句分析fruits表,执行的语句及结果如下:
sql 复制代码
ANALYZE TABLE fruits;
  • 结果说明

Msg_text: Table is already up to date. 表示表已经是最新的,无需重新分析。
Msg_text: OK 表示分析操作成功完成。

  1. 使用CHECK TABLE语句检查表fruits,执行的语句及结果如下:
sql 复制代码
CHECK TABLE fruits;
  • 结果说明

Msg_text: Table is marked as crashed and should be repaired. 表示表被标记为崩溃,需要修复。
Msg_text: Table 'fruits' is marked as crashed and should be repaired. 同样表示表被标记为崩溃,需要修复。

  • 修复方法及其修复结果
sql 复制代码
REPAIR TABLE fruits;

Msg_text: OK 表示修复操作成功完成。
Msg_text: The repair has been completed. 表示修复操作已经完成。


本文有关Mysql数据库性能优化内容已经讲完了, 明天再见啦👋

主页:【练小杰的CSDN】😆

ℹ️欢迎各位在评论区踊跃讨论,积极提出问题,解决困惑!!!

⚠️若博客里的内容有问题,欢迎指正,我会及时修改!!

相关推荐
️○-2 分钟前
后端之JPA(EntityGraph+JsonView)
java·数据库·后端·数据库架构
双手插兜-装高手14 分钟前
网络 - Socket编程
c语言·开发语言·网络·c++·经验分享
yqcoder16 分钟前
Express + MongoDB 实现新增用户密码加密
数据库·mongodb·express
是小崔啊16 分钟前
MongoDB03 - MongoDB索引,事务和安全
数据库·安全·mongodb
飞猿_SIR23 分钟前
最新版本Exoplayer(MediaX)实现K歌原伴唱包括单音轨和双音轨
android·ffmpeg·音视频
m0_7482333643 分钟前
精准删除:掌握SQL中的DELETE语句
数据库·sql·oracle
m0_748246871 小时前
flask后端开发(8):Flask连接MySQL数据库+ORM增删改查
数据库·mysql·flask
猿小喵1 小时前
MySQL缓存命中率
数据库·mysql·缓存
2501_903238651 小时前
JPA与存储过程的完美结合
数据库·oracle·个人开发
被程序耽误的胡先生2 小时前
复杂sql
java·数据库·sql