目录
前言
MySQL 社区版是全球广受欢迎的开源数据库的免费下载版本。它遵循 GPL 许可协议,由庞大、活跃的开源开发人员社区提供支持。
MySQL 社区版包括:可插拔的存储引擎架构、多种存储引擎(InnoDB、MyISAM、NDB (MySQL Cluster)、Memory、Merge、Archive、CSV、等等)、MySQL 复制可提高应用性能和可扩展性、MySQL 分区有助于增强大型数据库应用的性能和管理、存储过程可提高开发人员效率、触发器可在数据库层面实施复杂的业务规则、视图可确保敏感信息不受攻击、Performance Schema 可监视各个用户/应用的资源占用情况、Information Schema 有助于方便地访问元数据、MySQL 连接器(ODBC、JDBC、.NET 等)可以用多种语言构建应用、MySQL Workbench 可用于可视化建模、SQL 开发和管理。
本篇文章就围绕MySQL的性能优化及系统资源优化进行,通过本篇文章将对MySQL的优化有一个更深入的了解!由于篇幅较长,为了便于阅读和记忆,所以博主将其分成了一、二部分,第一部分主讲MySQL数据库的结构优化、性能调优,第二部分主讲系统资源调优、通过MySQL的系统配置参数实现。
MySQL性能调优和系统资源优化
一、MySQL性能调优和系统资源优化的目的
- 掌握 MySQL性能调优和系统资源优化到底优化了什么;
- 掌握 MySQL查询的优化方法;
- 掌握 MySQL数据库结构的优化方法;
- 掌握 MySQL服务器的优化方法;
二、MySQL性能调优和系统资源优化到底优化了什么
- 合理分配 MySQL资源、调整其系统参数使 MySQL运行速度更快、资源更节省;
- MySQL优化包括查询优化、更新优化、服务器优化等;
- MySQL基本优化原则:减少系统瓶颈,减少资源占用,增加系统的响应速度;
三、数据库性能参数
使用 SHOW STATUS 语句查看MySQL数据库的性能参数“ SHOW STATUS LIKE 'value' ”
如下图:
常用的参数:
参数名 | 说明 |
---|---|
Slow_queries | 慢查询次数 |
Com_% | MySQL的 CRUD相关操作的次数 |
Uptime | 上线总时长(或者连接到某个数据库的总时长) |
Max_used_connections_time | 最开始的连接时间(连接到某个数据库的时间点) |
更多优化参数配置,参看《 MySQL 性能优化实战,MySQL 性能调优和系统资源优化解决方案(二) 》
四、查询优化
关键字:EXPLAIN
在 MySQL 中可以使用 EXPLAIN 查看SQL语句的执行情况,用法:EXPLAIN SELECT * FROM table_name;
如下图:
字段说明:
字段名 | 说明 |
---|---|
id | SELECT 识别符,这个表示SELECT查询序列号 |
select_type |
表示 SELECT 语句的类型。取值: SIMPLE,表示简单查询,其中不包含连接查询和子查询; PRIMARY,表示主查询,或者是最外面的查询语句; UNION,表示连接查询的第2个或后面的查询语句; DEPENDENT UNION,UNION 中的第二个或后面的SELECT语句,取决于外面的查询; UNION RESULT,连接查询的结果; SUBQUERY,子查询中的第1个SELECT语句; DEPENDENT SUBQUERY,子查询中的第1个SELECT语句,取决于外面的查询; DERIVED,SELECT(FROM 子句的子查询) |
table | 表示查询的表 |
partitions | 分区信息 |
type |
表示表的连接类型。以下的连接类型的顺序是从最佳类型到最差类型: system,表仅有一行,这是const类型的特列,平时不会出现,这个也可以忽略不计; const,数据表最多只有一个匹配行,因为只匹配一行数据,所以很快,常用于 PRIMARY KEY 或者 UNIQUE 索引的查询,可理解为const是最优化的; eq_ref,mysql手册是这样说的:"对于每个来自于前面的表的行组合,从该表中读取一行。这可能是最好的联接类型,除了const类型。它用在一个索引的所有部分被联接使用并且索引是 UNIQUE 或 PRIMARY KEY"。eq_ref 可以用于使用=比较带索引的列; ref,查询条件索引既不是 UNIQUE 也不是 PRIMARY KEY 的情况。ref可用于=或<或>操作符的带索引的列; ref_or_null,该联接类型如同ref,但是添加了 MySQL 可以专门搜索包含 NULL 值的行。在解决子查询中经常使用该联接类型的优化; 以上这五种情况都是很常见的索引使用情况;
unique_subquery,该类型替换了下面形式的IN子查询的 ref: value IN (SELECT primary_key FROM single_table WHERE some_expr), unique_subquery 是一个索引查找函数,可以完全替换子查询,效率更高; index_subquery,该联接类型类似于 unique_subquery。可以替换 IN 子查询,但只适合下列形式的子查询中的非唯一索引: value IN (SELECT key_column FROM single_table WHERE some_expr); range,只检索给定范围的行,使用一个索引来选择行; index,该联接类型与ALL相同,除了只有索引树被扫描。这通常比ALL快,因为索引文件通常比数据文件小; ALL,对于每个来自于先前的表的行组合,进行完整的表扫描(这种类型的性能最差); |
possible_keys | 指出 MySQL 能使用哪个索引在该表中找到行。如果该列为 NULL,说明没有使用索引,可以对该列创建索引来提高性能。 |
key | 显示 MySQL 实际决定使用的键(索引)。如果没有选择索引,键是NULL; |
key_len |
显示 MySQL 决定使用的键长度。如果键是NULL,则长度为NULL。 注意:key_len 是确定了 MySQL 将实际使用的索引长度。 |
ref | 显示使用哪个列或常数与 key一起从表中选择行。 |
rows | 显示 MySQL 认为它执行查询时必须检查的行数。 |
filtered | 过滤器 |
Extra |
该列包含 MySQL 解决查询的详细信息。取值如下: Distinct,MySQL 发现第1个匹配行后,停止为当前的行组合搜索更多的行; |
查询索引使用注意事项:索引可以提高查询的速度,但并不是使用了带有索引的字段查询都会生效,有些情况下是不生效的,需要注意!
1、使用 LIKE关键字的查询
在使用 LIKE关键字进行查询时,如果匹配字符串的第一个字符为“%”,索引不起作用,只有“%”不在第一个位置,索引才会生效。
2、使用联合索引的查询
MySQL可以为多个字段创建索引,一个索引可以包括16个字段。对于联合索引,只有查询条件中使用了这些字段中第一个字段时,索引才会生效。
3、使用 OR关键字的查询
查询语句的查询条件中只有OR关键字,且OR前后的两个条件中的列都是索引时,索引才会生效,否则,索引不生效。
五、数据库结构优化
一个好的数据库设计方案对于数据库的性能往往会起到事半功倍的效果。需要考虑数据冗余、查询和更新的速度、字段的数据类型是否合理等多方面的内容。
1、将字段很多的表分解成多个表
对于字段较多的表,如果有些字段的使用频率很低,可以将这些字段分离出来形成新表。因为当一个表的数据量很大时,会由于使用频率低的字段的存在而变慢。
2、增加中间表
对于需要经常联合查询的表,可以建立中间表以提高查询效率。通过建立中间表,将需要通过联合查询的数据插入到中间表中,然后将原来的联合查询改为对中间表的查询。
3、增加冗余字段
设计数据表时应尽量遵循范式理论的规约(数据库设计三范式),尽可能的减少冗余字段,让数据库设计看起来精致、优雅。但是,合理的加入冗余字段可以提高查询速度。
表的规范化程度越高,表和表之间的关系越多,需要连接查询的情况也就越多,性能也就越差。
* 注意:冗余字段的值在一个表中修改了,就要想办法在其他表中更新,否则就会导致数据不一致的问题!
六、数据库数据操作优化
插入数据时,影响插入速度的主要是索引、唯一性校验、一次插入的数据条数等。
插入数据的优化,不同的存储引擎优化手段不一样,现在许多数据库管理系统都支持多种不同的存储引擎。MySQL 的核心就是存储引擎。
1、关于存储引擎
数据库存储引擎是数据库底层软件组织,数据库管理系统(DBMS)使用数据引擎进行创建、查询、更新和删除数据。不同的存储引擎提供不同的底层实现(如:存储机制,索引技巧,索引技巧,锁定水平),底层实现的差异带来的功能也就不同,在不同的场景下选择合适的存储引擎,可以让数据库的数据读写速度更快、效率更高。
MySQl数据库中的引擎(9个):InnoDB、MRG_MYISAM、MEMORY、BLACKHOLE、MyISAM、CSV、ARCHIVE、PERFORMANCE_SCHEMA、FEDERATED。
InnoDB 事务型数据库的首选引擎,支持事务安全表(ACID),支持行级锁和外键。MySQL 5.5.x 之后,InnoDB 作为默认存储引擎。
MyISAM 是基于 ISAM的存储引擎,并对其进行扩展,是在Web、数据仓储和其他应用环境下最常使用的存储引擎之一。MyISAM 拥有较高的插入、查询速度,但不支持事务。
MEMORY 存储引擎将表中的数据存储到内存中,为查询和检索其他数据提供快速访问。
通过指令 “ SHOW ENGINES; ” 查看,如下图:
常见的MySQL存储引擎的异同:
功能 | InnoDB | MyISAM | MEMORY | ARCHIVE |
---|---|---|---|---|
存储限制 | 64TB | 265TB | RAM | NONE |
支持事务 | YES | NO | NO | NO |
支持全文索引 | NO | YES | NO | NO |
支持B树索引 | YES | YES | YES | NO |
支持哈希索引 | NO | NO | YES | NO |
支持集群索引 | YES | NO | NO | NO |
支持数据索引 | YES | NO | YES | NO |
支持数据压缩 | NO | YES | NO | NO |
支持外键 | YES | NO | NO | NO |
支持数据缓存 | YES | NO | N/A | NO |
空间使用率 | 高 | 低 | N/A | N/A |
查看表的存储引擎类型(常见的两种查看方式):
SHOW CREATE TABLE tablename;
SHOW TABLE STATUS FROM dbname WHERE name = tablename;
如下图:
或者
修改表的存储引擎:
ALTER TABLE tablename ENGINE = InnoDB;
修改后如下图:
存储引擎的选型:
- InnoDB 用于事务处理应用程序,具有众多特性,包括 ACID 事务支持。如果应用中需要执行大量的 INSERT 或 UPDATE 操作,则应该使用 InnoDB,这样可以提高多用户并发操作的性能;
- 如果数据表只用来大量新增、查询的,MyISAM 引擎的效率更高;
- 如果只是临时存放数据,数据量不大,并且不需要较高的数据安全性,可以选择将数据存储在基于 MEMORY引擎的数据表中,MySQL中使用该引擎作为临时表或中间表来存放查询结果;
- 如果只提供高并发新增操作的,可以选择 ARCHIVE引擎,ARCHIVE引擎支持高并发的插入操作,但是本身并不是事务安全的,Archive 引擎非常适合存储归档数据,比如记录系统日志信息;
*注:在数据表中使用那种引擎需要根据实际的业务需求来判定,如果遇到需求变更,当前数据表的引擎不再适合于当前业务时,也可进行变更的操作(如何变更请往后看),一个数据库中多个表可以使用不同的引擎以满足各种性能和实际业务的需求,选择合适的存储引擎将会大大提高数据库的整体性能。
2、InnoDB
InnoDB是目前 MySQL的默认存储引擎,是目前使用最广泛的存储引擎。主要特点有:
- 支持事务(ACID)。默认的事务隔离级别为可重复度,通过MVCC(并发版本控制)来实现的;
- 支持自动增长列,通过 auto_increment来实现;
- InnoDB使用的锁粒度为行级锁,可以支持更高的并发;
- 支持从灾难中恢复表(通过 bin-log日志),容灾性强;
- 支持外键约束,虽然外键约束降低了表的查询速度,但是增加了表之间的耦合度;
- 配合热备工具可以支持在线热备份;
- 支持缓存(innodb_buffer_pool_size 来设置),通过缓冲池,将索引和数据全部缓存起来,加快查询的速度;
- 其数据的物理组织形式是群集表,所有的数据围绕主键来组织,索引和数据放在一起,构成一个数据块,位于B+树的叶子节点上;
InnoDB 的存储表和索引特点:
1)共享表空间存储:所有的表和索引存放在同一个表空间中。
2)多表空间存储:表结构放在frm文件,数据和索引放在IBD文件中。分区表的情况下,每个分区对应单独的IBD文件。
3、MyISAM
MyISAM 是一个基于 ISAM存储引擎,并对其进行扩展。它是在Web、数据仓储和其他应用环境下最常使用的存储引擎之一。MyISAM 拥有较高的数据新增、数据查询速度,但不支持事物。
使用 MyISAM引擎创建数据库,将产生3个文件,分别是(.frm, .MYD, .MYI):.frm 存储表的定义(也就是表结构),.MYD 存储表里面的数据,.MYD 存储索引。
MyISAM 特点:
- 支持大文件(长度可达63位),在大文件的文件系统和操作系统上被支持;
- 当删除、更新、新增操作混合使用的时候,动态的数据行将产生更少的碎片。这要通过合并相邻被删除的块,以及在下一个块被删除,就自动扩展到下一块;
- 每个 MyISAM表最大索引数是为64,可以通过重新编译来变更;
- 最大的键长度是1000字节,可以通过重新编译来变更;
- BLOB和TEXT类型的列可以被索引,支持FULLTEXT类型的索引,InnoDB不支持这种类型的索引;
- 索引列中允许为NULL,长度为0~1个字节;
- 数字键值以高字节优先被存储以允许一个更高的索引压缩;
- 每个 MyISAM类型的表都有一个AUTO_INCREMENT的内部列,当 INSERT和 UPDATE操作的时候该列被更新,同时AUTO_INCREMENT列将被刷新。所以说,MyISAM类型表的 AUTO_INCREMENT列更新比 InnoDB类型的AUTO_INCREMENT更快;
- 数据文件和索引文件放在不同目录;
- 每个字符列可以有不同的字符集;
- VARCHAR 的列长度可固定可动态;
- VARCHAR和CHAR列可以多达64KB;
MyISAM 支持的三种存储格式:
1)、静态表(固定长度)
这种存储格式的优点在于存储速度非常快,容易发生缓存,而且表发生损坏后也容易修复。缺点是占用的空间相对动态表较多。默认的存储格式。
2)、动态表(可变长度)
优点是节省空间,缺点是一旦出错恢复起来比较麻烦。占用的空间相对静态表较少,如果频繁的更新删除操作会产生碎片,需要定期执行 optimize table或 myisamchk -r命令来改善性能。
3)、压缩表
使用 myisampack工具创建,占用空间非常小,因为每个记录是被单独压缩的,访问开支也非常的小。在数据文件发生错误时候,可以使用 check table工具来检查,通过 repair table工具来恢复。
MyISAM和InnoDB的区别
- MyISAM 是非事务安全型的,InnoDB 是事务安全型的;
- MyISAM 锁的粒度是表级,InnoDB 支持行级锁定;
- MyISAM 支持全文类型索引,InnoDB 不支持全文索引;
- MyISAM 相对简单,所以在效率上要优于 InnoDB,小型应用可以考虑使用 MyISAM;
- MyISAM 表是保存成文件的形式,在跨平台的数据转移中使用 MyISAM存储会省去不少的麻烦;
- InnoDB 表比 MyISAM表更安全,可以在保证数据不会丢失的情况下,切换非事务表到事务表(ALTER TABLE tablename ENGINE = InnoDB);
4、MEMORY
MEMORY 引擎默认使用哈希(HASH)索引,其速度比B树要快,但也可以使用B树索引。由于 MEMORY引擎所存储的数据都被保存在内存中,以供查询和引用的其他表数据实现快速访问,但是其保存的数据是具有不稳定性的,如果一旦 mysqld进程发生异常、重启或服务器异常宕机等情况都会导致数据的丢失。MEMORY 引擎一般适用于生命周期短,且只使用一次的数据表。所以,一般都是在创建临时表时才会使用到。
MEMORY 特点:
- 表中可以存在非唯一键值;
- 对于字符串类型的数据,只支持固定长度的行,并且 VARCHAR会被自动存储为 CHAR类型;
- 不支持BLOB或TEXT类型;
- 支持 AUTO_INCREMENT列和可包含NULL值的列的索引;
- 在所由客户端之间共享;
- 不在使用的内容,需要释放其占用的内存空间,通过执行DELETE FROM或TRUNCATE TABLE,或者删除整个表(使用DROP TABLE)来释放占用的资源;
5、其它引擎
ARCHIVE
ARCHIVE > 归档,仅仅支持插入和查询两种功能。ARCHIVE 在 MySQL5.5以后支持索引功能,支持良好的压缩机制,使用zlib实现压缩,在记录请求的时候实时压缩,经常被用来作为仓库使用。适用于存储大量的独立的作为历史记录的数据,例如系统日志的记录,对插入速度要求较高,查询不经常使用的,因为该引擎对查询的支持较差。
CSV
文件结构组成包括:.frm表结构描述、.csv数据、.csm表状态、当前记录数量等。
特点:
- 没有索引、不能为NULL、不支持自增长;
- 更新和删除时先写入到临时文件,然后在 rnd_end()函数中重新生成数据文件;
- 支持直接编辑数据文件;
- 以CSV引擎存储的数据,引号包含,逗号隔开;
- 数据以文本方式存储在文件中;
- CSV引擎可以将csv文件作为 MySQL的表进行处理,其存储格式类似于普通的csv文件;
BLACKHOLE
BLACKHOLE 引擎支持事务,而且支持 mvcc的行级锁,写入 BLACKHOLE引擎表中的任何数据都会消失,主要用于做日志记录或同步归档的中继存储,BLACKHOLE 引擎除非有要求使用,否则不会使用到。
PERFORMANCE_SCHEMA
PERFORMANCE_SCHEMA 引擎是MySql 5.5新推出的一个引擎,主要是用来收集数据库服务器的性能参数。但是我们无法创建该类型的表,需要在配置文件my.cnf中进行配置才能生效。
特点:
- 提供进程的详细信息,包括锁、互斥变量、文件信息;
- 历史的事件汇总信息,提供为 MySql服务器的性能情况做出判断;
- 对新增和删除监控事件点都非常容易,并可以随意的改变 Mysql服务器的监控周期;
FEDERATED
FEDERATED 引擎可以将不同的 Mysql服务器联合起来,在逻辑上组成一个完整的数据库,FEDERATED引擎非常适合分布式数据库应用。
FEDERATED 引擎支持在本地数据库中访问远程数据库中的数据,发送到 FEDERATED引擎表的查询请求会被转发送到远程数据库的表上执行,而 FEDERATED引擎数据库本身是不存储数据的。
特点:
- 不支持事务;
- 不支持表结构修改;
- 不支持ALTER TABLE指令;
- 执行TRUNCATE指令时,会同时清楚远程关联表中的数据;
- 执行DROP指令时,不会删除远程关联表;
- 本地的表结构必须同远程的完全一致;
- 远程关联表仅限于MySQL;
- 本地表与远程关联表通过 TCP长连接进行的,支持多客户端使用,所以不用担心频繁建立连接带来的网络带宽的开销;
- 一般创建的表会生成表的定义文件和数据文件,通过 FEDERATED引擎创建的表只在本地生成表的定义文件,数据文件则存在于与之关联的远程数据库中,通过 FEDERATED引擎可以实现类似于 Oracle下DBLINK的远程数据访问功能;
6、数据库引擎优化
MyISAM
禁用索引,对于非空表,插入记录时,MySQL会根据表的索引对插入的记录建立索引。如果插入大量数据,建立索引会降低插入数据速度。为了解决这个问题,可以在批量插入数据之前禁用索引,数据插入完成后再开启索引。
禁用索引:
ALTER TABLE table_name DISABLE KEYS;
开启索引语句:
ALTER TABLE table_name ENABLE KEYS;
对于空表批量插入数据,则不需要进行操作,因为 MyISAM引擎的表是在导入数据后才建立索引。
禁用唯一性检查:
唯一性校验会降低插入记录的速度,可以在插入记录之前禁用唯一性检查,插入数据完成后再开启。
禁用唯一性检查的语句:
SET UNIQUE_CHECKS = 0;
开启唯一性检查的语句:
SET UNIQUE_CHECKS = 1;
批量插入数据:
插入数据时,可以使用一条 INSERT语句插入一条数据,也可以插入多条数据。当然同时插入多条数据的方式的插入速度比第一种方式快。
使用 LOAD DATA INFILE:
当需要批量导入数据时,使用 LOAD DATA INFILE语句比 INSERT语句插入速度快很多。
InnoDB
禁用唯一性检查:
用法同MyISAM一样。
禁用外键检查:
插入数据之前执行禁止对外键的检查,数据插入完成后再恢复,可以提高插入速度。
禁用:SET FOREIGN_KEY_CHECKS = 0;
开启:SET FOREIGN_KEY_CHECKS = 1;
禁止自动提交:
插入数据之前执行禁止事务的自动提交,数据插入完成后再恢复,可以提高插入速度。
禁用:SET AUTOCOMMIT = 0;
开启:SET AUTOCOMMIT = 1;
七、子查询优化
MySQL 从4.1版本开始支持子查询,使用子查询进行 SELECT语句嵌套查询,可以一次完成很多逻辑上需要多个步骤才能完成的 SQL操作。子查询虽然很灵活,但是执行效率并不高。执行子查询时,MYSQL首先需要创建临时表,查询完毕后再删除这些临时表,所以,子查询的速度会受到一定的影响。
子查询优化方法
可以使用连接查询(JOIN)来代替子查询,连接查询时不需要建立临时表,其速度比子查询快。
参考文档:
MySQL中文官网:【MySQL 性能调优和优化资源】
好了,关于 MySQL 性能优化实战,MySQL 性能调优和系统资源优化解决方案(一) 就写到这儿了,如果还有什么疑问或遇到什么问题欢迎扫码提问,也可以给我留言哦,我会一一详细的解答的。
歇后语:“ 共同学习,共同进步 ”,也希望大家多多关注CSND的IT社区。
作 者: | 华 仔 |
联系作者: | [email protected] |
来 源: | CSDN (Chinese Software Developer Network) |
原 文: | https://blog.csdn.net/Hello_World_QWP/article/details/104900695 |
版权声明: | 本文为博主原创文章,请在转载时务必注明博文出处! |