2020重新出发,MySql基础,性能优化

@[toc]

MySQL性能优化

应用开发过程中,由于初期数据量小,开发人员更重视功能上的实现,但是当应用系统正式上线后,随着生产数据量的急剧增长,数据库开始显露性能问题,对生产的影响也越来越大,因此我们必须对它们进行优化。

性能优化是通过某些有效的方法提高 MySQL 数据库的性能,主要是为了使 MySQL 数据库运行速度更快、占用的磁盘空间更小。

MySQL性能优化简述

简而言之,性能优化就是在不影响系统能正确运行的前提下,运行速度更快,完成特定功能所需的时间更短。

我们可以通过某些有效的方法来提高 MySQL 数据库的性能,目的是让 MySQL 数据库的运行速度更快、占用的磁盘空间更小。

性能优化包括很多方面,例如优化查询速度、优化更新速度和优化 MySQL 服务器等。通过不同的优化方式达到提高 MySQL 数据库性能的目的。优化数据库是数据库管理员和开发人员的必备技能。

MySQL 数据库的用户和数据非常少时,很难判断数据库性能的好坏。只有当长时间运行,并且有大量用户进行频繁操作时,MySQL 数据库的性能才能体现出来。

  • 例如,一个每天有几万用户同时在线的大型网站,它的数据库性能的优劣就很明显。这么多用户同时连接 MySQL 数据库,并且进行查询、插入和更新的操作。如果 MySQL 数据库的性能很差,很可能无法承受如此多用户的同时操作。另外,如果用户查询一条记录需要花费很长时间,那么用户很难会喜欢这个网站。

[图片上传失败...(image-a6993b-1599011009884)]

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

例如,

  • 通过优化文件系统,提高磁盘 I\O 的读写速度;
  • 通过优化操作系统调度策略,提高 MySQL 在高负荷情况下的负载能力;
  • 优化表结构、索引、查询语句等使查询响应更快。

如果 MySQL 数据库中需要进行大量的查询操作,那么就需要对查询语句进行优化。对于耗费时间的查询语句进行优化,可以提高整体的查询速度。如果连接 MySQL 数据库的用户很多,那么就需要对 MySQL 服务器进行优化。否则,大量的用户同时连接 MySQL 数据库,可能会造成数据库系统崩溃。

系统的分析效率低下的 SQL 两种方法:

使用 SHOW STATUS 命令

数据库管理员可以使用 SHOW STATUS 语句查询 MySQL 数据库的性能参数,了解各种 SQL 的执行频率。语法形式如下:

SHOW STATUS LIKE 'value';

其中,value 参数是常用的几个统计参数,常用参数介绍如下:

  • Connections:连接 MySQL 服务器的次数;
  • Uptime:MySQL 服务器的上线时间;
  • Slow_queries:慢查询的次数;
  • Com_select:查询操作的次数;
  • Com_insert:插入操作的次数,对于批量插入操作,只累加一次;
  • Com_update:更新操作的次数;
  • Com_delete:删除操作的次数。

以上参数针对于所有存储引擎的表,下面几个参数只针对 InnoDB 存储引擎。

  • Innodb_rows_read:表示 SELECT 语句查询的记录数;
  • Innodb_rows_inserted:表示 INSERT 语句插入的记录数;
  • Innodb_rows_updated:表示 UPDATE 语句更新的记录数;
  • Innodb_rows_deleted:表示 DELETE 语句删除的记录数。

比如,需要查询 MySQL 服务器的连接次数,可以执行下面的 SHOW STATUS 语句:

SHOW STATUS LIKE 'Connections';

查询其它参数的方法和以上参数的查询方法相同。

通过以上几个参数,可以很容易的了解当前数据库的应用是以插入为主还是以查询为主,以及各种类型的 SQL 语句的大致执行比例。然后根据分析结果,进行相应的性能优化。

使用慢查询日志

慢查询次数参数可以结合慢查询日志,找出慢查询语句,然后针对慢查询语句进行表结构优化或者查询语句优化。

MySQL 查询分析器

查询是数据库中最频繁的操作,提高查询速度可以有效的提高 MySQL 数据库的性能。

通过对查询语句的分析,可以了解查询语句的执行情况,找出查询语句执行的瓶颈,从而优化查询语句。在 MySQL 中,可以使用 EXPLAIN 和 DESCRIBE 获取 MySQL 执行 SELECT 语句的信息,来分析查询语句

EXPLAIN 语句的基本语法如下:

EXPLAIN SELECT 语句;

“SELECT 语句”参数一般为数据库查询命令,如“SELECT * FROM tb_student”。通过 EXPLAIN 关键字可以分析后面 SELECT 语句的执行情况,并且能够分析出所查询表的一些内容。

EXPLAIN

例子:下面使用 EXPLAIN 语句来分析一个查询语句。代码执行如下:

mysql> EXPLAIN SELECT * FROM tb_student \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: tb_student
   partitions: NULL
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 7
     filtered: 100.00
        Extra: NULL
1 row in set, 1 warning (0.01 sec)

对以上结果中参数说明如下:

  1. id:表示 SELECT 语句的编号,也就是在整个查询中 SELECT 的位置。如果在语句中没子查询或关联查询,只有唯一的 SELECT,每行都将显示 1。否则,内层的 SELECT 语句一般会顺序编号,对应于其在原始语句中的位置。
  2. select_type:表示 SELECT 语句的类型,该参数有以下几个常用的取值:
    • SIMPLE:表示简单查询,其中不包括连接查询和子查询;
    • PRIMARY:表示主查询,或者是最外层的查询语句;
    • UNION:表示连接查询的第二个或后面的查询语句;
    • DEPENDENT UNION:连接查询中的第 2 个或后面的 SELECT 语句,取决于外面的查询;
    • UNION RESULT:连接查询的结果;
    • SUBQUERY:子查询中的第 1 个 SELECT 语句;
    • DEPENDENT SUBQUERY:子查询中的第 1 个 SELECT 语句,取决于外面的查询;
    • DERIVED:导出表的 SELECT(FROM 子句的子查询)
  3. table:表示查询的表;
  4. partitions:
  5. type:表示表的连接类型。该参数有以下几个常用的取值,范围从 NULL 到 ALL。下面按照最佳类型到最差类型排序:
    • NULL:不用访问表或者索引,直接就能得到结果;
    • system:表示表中只有一条记录;
    • const:表示表中有多条记录,但只从表中查询一条记录;
    • eq _ref:类似 ref,表示多表连接时,后面的表使用了 UNIQUE 或者 PRIMARY KEY;
    • ref:表示多表查询时,后面的表使用了普通索引;
    • range:表示查询语句中给出了查询范围,常见于 <、<=、>、>=、between 等操作符;
    • index:表示对表中的索引进行了完整的扫描,MySQL 遍历整个索引来查询匹配的行;
    • ALL:表示对表进行了完整的扫描,MySQL 遍历全表来找到匹配的行。
  6. possible_keys:表示查询中可以使用的索引;
  7. key:表示实际查询中使用到的索引;
  8. key_len:表示索引字段的长度;
  9. ref:表示使用哪个列或常数与索引一起来查询记录;
  10. rows:表示查询的行数;
  11. filtered:MySQL 5.7 版本之前使用 EXPLAIN EXTENDED 时会出现这个字段,MySQL 5.7 版本之后包括 5.7 版本默认就有这个字段。这个字段表示存储引擎返回的数据在 server 层过滤后,剩下多少满足查询记录数量的比例。注意是百分比,不是具体记录数。
  12. Extra:表示查询过程的附件信息。

DESCRIBE

DESCRIBE 语句的使用方法与 EXPLAIN 语句一样,DESCRIBE 语句的语法形式如下:

DESCRIBE SELECT语句;

DESCRIBE 可以缩写成 DESC。

索引对查询速度的影响

索引是数据库优化中最常用也是最重要的手段之一,通过索引可以帮助用户解决大多数的 SQL 性能问题。

多数情况下,查询速度很慢时,加上索引便能解决问题。但也并非总是如此,因为优化不是件简单的事情。但是如果你不使用索引,在许多情况下,尝试通过其它途径来提高性能都纯粹是在浪费时间。应该首先使用索引来最大程度的改善性能,然后再看看是否还有其它有用的技术。

索引提供了高效访问数据的方法,能够快速的定位表中的某条记录,加快数据库查询的速度,从而提高数据库的性能。

如果查询时不使用索引,那么查询语句将查询表中的所有字段。这样查询的速度会很慢。使用索引进行查询,查询语句不必读完表中的所有记录,而只查询索引字段。这样可以减少查询的记录数,达到提高查询速度的目的。

下面通过对比使用索引和不使用索引来分析索引对查询速度的影响。

为了便于读者更好的理解,分析之前,我们先查询一下 tb_students_info 数据表中的记录,SQL 语句和运行结果如下:

mysql> SELECT * FROM tb_students_info;
+----+------+
| id | name |
+----+------+
|  1 | 张三 |
|  2 | 李四 |
|  3 | 王五 |
|  4 | 赵六 |
|  5 | 周七 |
|  6 | 吴八 |
|  7 | 朱九 |
|  8 | 苏十 |
+----+------+
8 rows in set (0.02 sec)

使用 EXPLAIN 分析未使用索引时的查询情况,SQL 语句和运行结果如下:

mysql> EXPLAIN SELECT * FROM tb_students_info WHERE name='张三' \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: tb_students_info
   partitions: NULL
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 8
     filtered: 12.50
        Extra: Using where
1 row in set, 1 warning (0.00 sec)

由结果可以看到,rows 列的值是 8,说明查询语句扫描了表中的 8 条记录。

注意:没有索引的表就相当于一组无序的行,如果我们想找到某条记录就必须检查表的每一行,看看它是否与那个期望值相匹配。这是一个全表扫描操作,其效率很低,如果表很大,而且仅有少数几条记录与搜索条件相匹配,那么整个扫描过程的效率将会超级低。

在 tb_students_info 表的 name 字段添加索引,SQL 语句和运行结果如下:

mysql> CREATE INDEX index_name ON tb_students_info(name);
Query OK, 8 rows affected (0.14 sec)

使用 EXPLAIN 再次执行上面的查询语句,SQL 语句和运行结果如下:

mysql> EXPLAIN SELECT * FROM tb_students_info WHERE name='张三' \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: tb_students_info
   partitions: NULL
         type: ref
possible_keys: index_name
          key: index_name
      key_len: 63
          ref: const
         rows: 1
     filtered: 100.00
        Extra: NULL
1 row in set, 1 warning (0.00 sec)

结果显示,rows 列的值为 1,表示这个查询语句只扫描了表中的 1 条记录。创建索引后访问的行由 8 行减少到 1 行,其查询速度自然比扫描 8 条记录快。而且 possible_keys 和 key 的值都是 index_name,这说明查询时使用了 index_name 索引。所以,在查询操作中,使用索引不仅能自动优化查询效率,还会降低服务器的开销。

注意:由于 tb_students_info 表中记录较少,所以在这没有分析运行时间。表中记录多时,运行时间的差异也会体现出索引对查询速度的影响。

MySQL优化数据库结构

一个好的数据库设计方案会对数据库的性能起到事半功倍的效果。合理的数据库结构不仅可以使数据库占用更小的磁盘空间,而且能够使查询速度更快。

数据库结构是否合理,需要考虑是否存在冗余、对表的查询和更新的速度、表中字段的数据类型是否合理等多方面的内容

分解表

有些表在设计时设置了很多的字段,而有些字段的使用频率非常低。这样当这个表的数据量很大时,查询数据的速度就会很慢。我们可以将这些使用频率较低的字段分离出来形成新表。

例子:在 student 数据表中有很多字段,其中 comment 字段用来存储学生的备注信息。

备注信息的内容特别多,但是该字段很少使用。这时就可以分解出另外一个表。分解出的表为 student_comment,表中存储 2 个字段

  • id :id 为学生的学号
  • comment:comment 为学生备注信息

student_comment 的表结构如下:

mysql> DESC `student_comment`;
+---------+---------+------+-----+---------+-------+
| Field   | Type    | Null | Key | Default | Extra |
+---------+---------+------+-----+---------+-------+
| id      | int(11) | NO   | PRI | NULL    |       |
| comment | text    | YES  |     | NULL    |       |
+---------+---------+------+-----+---------+-------+
2 rows in set (0.00 sec)

如果需要查询某个学生的备注信息,可以使用学号(id)来查询。如果需要将学生的学籍信息与备注信息同时显示,可以使用表连接查询 student 表和 student_comment 表,查询语句如下:

SELECT * FROM student, student_comment WHERE student.id=student_comment.id;

通过以上方法,可以有效的提高 student 表的查询效率。

增加中间表

表连接会降低数据库的查询速度,所以对于经常使用表连接查询的表,我们可以建立中间表来提高查询速度。

首先分析经常需要同时查询哪几个表中的哪些字段,然后将这些字段建立一个中间表,并将原来那几个表的数据插入到中间表中,之后就可以使用中间表来进行查询和统计了。

例子:下面有两个数据表,分别是 student(学生)表和 score(分数)表。这两个表的结构如下:

mysql> DESC student;
+---------+-------------+------+-----+---------+-------+
| Field   | Type        | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| id      | int(11)     | NO   | PRI | NULL    |       |
| name    | varchar(20) | YES  |     | NULL    |       |
| sex     | varchar(4)  | YES  |     | NULL    |       |
| birth   | date        | YES  |     | NULL    |       |
| address | varchar(50) | YES  |     | NULL    |       |
+---------+-------------+------+-----+---------+-------+
5 rows in set (0.00 sec)

mysql> DESC score;
+--------+-------------+------+-----+---------+-------+
| Field  | Type        | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| id     | int(11)     | NO   | PRI | NULL    |       |
| stu_id | int(11)     | NO   | MUL | NULL    |       |
| c_name | varchar(20) | YES  |     | NULL    |       |
| grade  | int(11)     | YES  |     | NULL    |       |
+--------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)

实际应用中,经常需要查询学生的学号、姓名和成绩。对于这种情况,我们可以创建一个 temp_score 表。temp_score 表中存储 3 个字段,分别是 id、name 和 grade。

创建 temp_score 的 SQL 语句如下:

mysql> CREATE TABLE temp_score(
-> id INT NOT NULL,
-> name VARCHAR(20) NOT NULL,
-> grade FLOAT
-> );
Query OK, 0 rows affected (0.00 sec)

然后从 student 表和 score 表中将记录导入到 temp_score 表中。INSERT 语句如下:

INSERT INTO temp_score SELECT student.id, student.name, score.grade
FROM student, score WHERE student.id=score.stu_id;

将这些数据插入到 temp_score 表中以后,可以直接从 temp_score 表中查询学生的学号、姓名和成绩。这样就省去了每次查询时进行表连接,提高了数据库的查询速度。

增加冗余字段

一般情况下,设计数据库时应尽量让表符合三大范式。但是,有时为了提高查询速度,可以有意识地在表中增加冗余字段。

表的规范化程度越高,表与表之间的关系就越多,查询时也就经常需要在多个表之间进行连接查询,而连接操作会降低查询速度。

  • 例如,学生的信息存储在 student 表中,院系信息存储在 department 表中。通过 student 表中的 dept_id 字段与 department 表建立关联关系。

如果要查询一个学生所在系的名称,就必须从 student 表中查找学生所在院系的编号(dept_id),然后根据这个编号去 department 查找系的名称。这个连接查询会浪费很多的时间。因此可以在 student 表中增加一个冗余字段 deptname,用来存储学生所在院系的名称。这样就不用每次都进行连接操作了。

分解表、增加中间表和增加冗余字段都浪费了一定的磁盘空间。从数据库性能的角度来看,增加少量的冗余来提高数据库的查询速度是可以接受的。是否通过增加冗余来提高数据库性能,这要根据 MySQL 服务器的具体要求来定。如果磁盘空间很大,可以考虑牺牲一点磁盘空间。

MySQL优化插入数据速度

在 MySQL 中,向数据表插入数据时,索引、唯一性检查、数据大小是影响插入速度的主要因素。

根据不同情况,可以分别进行优化。

MyISAM 引擎表优化方法

禁用索引

对非空表插入数据时,MySQL 会根据表的索引对插入的记录进行排序。插入大量数据时,这些排序会降低插入数据的速度。为了解决这种情况,可以在插入数据之前先禁用索引,等到数据都插入完毕后在开启索引。

禁用索引的语句为:

ALTER TABLE table_name DISABLE KEYS;

重新开启索引的语句为:

ALTER TABLE table_name ENABLE KEYS;

对于新创建的表,可以先不创建索引,等到数据都导入以后再创建索引,这样可以提高导入数据的速度。

禁用唯一性检查

插入数据时,MySQL 会对插入的数据进行唯一性检查。这种唯一性检验会降低插入数据的速度。为了降低这种情况对查询速度的影响,可以在插入数据前禁用唯一性检查,等到插入数据完毕后在开启。

禁用唯一性检查的语句为:

SET UNIQUE_CHECKS=0;

开启唯一性检查的语句为:

SET UNIQUE_CHECKS=1;

使用批量插入

在 MySQL 中,插入多条数据有 2 种方式。第一种是使用一个 INSERT 语句插入多条数据。INSERT 语句的情形如下:

INSERT INTO items(name,city,price,number,picture) VALUES ('耐克运动鞋','广州',500,1000,'001.jpg'),('耐克运动鞋2','广州2',500,1000,'002.jpg');

第二种是一个 INSERT 语句只插入一条数据,执行多个 INSERT 语句来插入多条数据。INSERT 语句的情形如下:

INSERT INTO items(name,city,price,number,picture) VALUES('耐克运动鞋','广州',500,1000,'001.jpg');
INSERT INTO items(name,city,price,number,picture) VALUES('耐克运动鞋2','广州',500,1000,'002.jpg');

一次性插入多条数据和多次插入数据所耗费的时间是不一样的。第一种方式减少了与数据库之间的连接等操作,其速度比第二种方式要快一些。所以插入大量数据时,建议使用第一种方法。

注意:如果能用 LOAD DATA INFILE 语句,就尽量用 LOAD DATA INFILE 语句。因为 LOAD DATA INFILE 语句导入数据的速度比 INSERT 语句的速度快。

InnoDB 引擎表优化方法

禁用索引&禁用唯一性检查

同 MyISAM 引擎相同,插入数据之前先禁用索引,等到数据都插入完毕后在开启索引。

禁用外键检查

使用外键时,在子表中插入一条数据,首先会检查主表中是否有相应的主键值,然后锁定主表的记录,在插入值。相比较,使用外键多了2步操作,速度会慢一些。所以我们可以在插入数据之前禁止对外键的检查,数据插入完成之后再恢复对外键的检查。不多对于数据完整性要求较高的系统不建议使用。

禁用外键检查语句为:

SET FOREIGN_KEY_CHECKS=0; 

恢复对外键的检查语句为:

SET FOREIGN_KEY_CHECKS=1;

禁止自动提交

MySQL 的事务自动提交模式默认是开启的,其对 MySQL 的性能也有一定得影响。也就是说如果你插入了 1000 条数据,MySQL 就会提交 1000 次,这大大影响了插入数据的速度。而如果我们把自动提交关掉,通过程序来控制,只要一次提交就可以了。

所以插入数据之前可以先禁止事务的自动提交,待数据导入完成之后,再恢复自动提交操作。

禁止自动提交语句为:

SET AUTOCOMMIT=0; 

恢复自动提交语句为:

SET AUTOCOMMIT=1;

优化MySQL服务器

MySQL 中,可以通过两个方面来优化服务器,即硬件和配置参数的优化。通过这些优化方式,可以提高 MySQL 的运行速度。

优化服务器硬件

服务器的硬件直接决定着 MySQL 数据库的性能。例如,增加内存和提高硬盘的读写速度,可以提高 MySQL 数据库的查询、更新的速度。

优化服务器硬件的方法主要有以下几种:

  • 配置较大的内存
  • 配置高速磁盘系统,以减少读盘的等待时间,提高响应速度
  • 合理分布磁盘 I/O,把磁盘 I/O 分散在多个设备上,以减少资源竞争,提高并行操作能力
  • 配置多处理器,MySQL 是多线程的数据库,多处理器可同时执行多个线程

随着硬件技术的成熟,硬件的价格也随之降低。现在普通的个人电脑都已经配置了 8GB 内存,甚至一些个人电脑配置 16GB/32GB/64GB 内存。因为内存的读写速度比硬盘的读写速度快。可以在内存中为 MySQL 设置更多的缓冲区,这样可以提高 MySQL 的访问的速度。如果将查询频率很高的记录存储在内存中,那么查询速度就会很快。

如果条件允许,可以将内存提高。并且选择 my-innodb-heavy-4G.ini 作为 MySQL 数据库的配置文件。但是,这个配置文件主要支持 InnoDB 存储引擎的表。如果使用 8GB 内存,可以选择 my-huge.ini 作为配置文件。MySQL 所在的计算机最好是专用数据库服务器,这样数据库就可以完全利用该机器的资源。

服务器类型分为 Developer Machine、Server Machine 和 Dedicate MySQL Server Machine。其中 Developer Machine 用来做软件开发的时候使用,数据库占用的资源比较少。后面两者占用的资源比较多,尤其是 Dedicate MySQL Server Machine,其几乎要占用所有的资源。

还可以使用多块磁盘来存储数据。这样可以从多个磁盘上并行读取数据,提高数据库读取数据的速度。通过镜像机制可以将不同计算机上的 MySQL 服务器进行同步,这些 MySQL 服务器中的数据都是一样的。

通过不同的 MySQL 服务器来提供数据库服务,这样可以降低单个 MySQL 服务器的压力,从而提高 MySQL 的性能。

优化MySQL参数

和大多数数据库一样,MySQL 提供了很多参数来进行服务器的优化设置。数据库服务器第一次启动时,很多参数都是默认设置的,这在实际应用中并不能完全满足需求,为此数据库管理员要进行必要的设置。

查看性能参数的方法

MySQL 服务器启动之后,可以使用 SHOW VARIABLES 命令查看系统参数,也可称为静态参数。这些参数是系统默认或者 DBA 调整优化后的参数,可以通过 SET 命令或在配置文件中修改。

使用 SHOW STATUS 命令查询服务器运行的实时状态信息,也就是动态参数。便于 DBA 查看当前 MySQL 运行的状态,做出相应优化,不能手动修改。

例子:下面为使用 SHOW VARIABLES 和 SHOW STATUS 命令的实例。

mysql> SHOW VARIABLES LIKE 'key_buffer_size';
+-----------------+----------+
| Variable_name   | Value    |
+-----------------+----------+
| key_buffer_size | 33554432 |
+-----------------+----------+
1 row in set, 1 warning (0.00 sec)

mysql> SHOW STATUS LIKE 'key_read_requests';
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| Key_read_requests | 149   |
+-------------------+-------+
1 row in set (0.01 sec)

设置优化性能参数

在 MySQL 中,有些参数直接影响到系统的性能。我们可以通过优化 MySQL 的参数提高资源利用率,从而达到提高 MySQL 服务器性能的目的。

以下配置参数都在 my.cnf 或者 my.ini 文件的 [mysqld] 组中。

  1. key_buffer_size(针对MyISAM存储引擎):表示索引缓存的大小,这个参数是对 MyISAM 表性能影响最大的一个参数。值越大,索引进行查询的速度越快。
    • 通过检查状态值 key_read_requests 和 key_reads,可以知道 key_buffer_size 的值是否合理。正常情况下,key_reads / key_read_requests 的比例值需小于 0.01。
  2. table_cache(针对MyISAM存储引擎):表示数据库用户同时打开的表的个数。值越大,能够同时打开的表的个数越多。需要注意的是,这个值不是越大越好,因为同时打开的表太多会影响操作系统的性能。
    • 在设置该参数的时候,可以通过 open_tables 和 opened_tables 变量的值来确定该参数的值。open_tables 参数表示当前打开的表缓存数,opened_tables 参数表示曾经打开的表缓存数。
    • 如果 open_tables 的值已经接近 table_cache 的值,且 opened_tables 还在不断变大,则说明 MySQL 正在将缓存的表释放以容纳新的表,此时可能需要加大table_cache 的值。对于大多数情况,比较适合的值如下:
      • open_tables / opened_tables >= 0.85
      • open_tables / table_cache <= 0.95
    • 执行 FLUSH TABLE 操作后,系统会关闭一些当前没有使用的表缓存,因此 FLUSH TABLE 后,open_tables 参数的值会变小,opened_tables 参数的值不会变。
  3. query_cache_size:表示查询缓存区的大小。使用查询缓存区可以提高查询的速度。内存中会为 MySQL 保留部分的缓存区,这些缓存区可以提高 MySQL 的处理速度。可以从以下几个方面考虑如何设置该参数的大小:
    • 查询缓存对 DDL 和 DML 语句的性能的影响
    • 查询缓存的内部维护成本
    • 查询缓存的命中率以及内存使用率等因素
  4. query_cache_type:表示查询缓冲区的开启状态,用于控制查询结果是否放到查询缓存中。这种方式只适用于修改操作少且经常执行相同的查询操作的情况,其默认值为 0。
    • 值为 0 表示关闭;
    • 值为 1 表示开启;
    • 值为 2 表示按要求使用查询缓存区,只有 SELECT 语句中使用了 SQL_CACHE 关键字,查询缓存区才会使用。例如,SELECT SQL_CACHE * FROM student。
  5. max_connections:表示数据库的最大连接数,默认值为 100。参数最大值不能超过 16384,即使超过也以 16384 为准。该参数设置过小的最明显特征是出现“Too many connections”错误。当然连接数也不是越大越好,因为这些连接会浪费内存的资源。
  6. sort_buffer_size:表示排序缓存区的大小。值越大,排序的速度越快。
  7. read_buffer_size:表示为每个线程保留的缓冲区的大小。当线程需要从表中连续读取记录时需要用到这个缓冲区。
  8. read_rnd_buffer_size:表示为每个线程保留的缓冲区的大小,与 read_buffer_size 相似。但主要用于存储按特定顺序读取出来的记录。
  9. innodb_buffer_pool_size:表示 InnoDB 类型的表和索引的最大缓存。值越大,查询的速度越快。但是这个值太大了也会影响操作系统的性能。
  10. 调优参考计算方法:
    • val = Innodb_buffer_pool_pages_data / Innodb_buffer_pool_pages_total * 100%
    • val > 95% 则考虑增大 innodb_buffer_pool_size, 建议使用物理内存的 75%
    • val < 95% 则考虑减小 innodb_buffer_pool_size, 建议设置为:Innodb_buffer_pool_pages_data * Innodb_page_size * 1.05 / (102410241024)
  11. innodb_log_file_size:该参数的作用是设置日志组中每个日志文件的大小。该参数在高写入负载尤其是大数据集的情况下很重要,这个值越大则性能相对较高。最好不要超过 innodb_log_files_in_group * innodb_log_file_size 的 0.75。
  12. innodb_log_files_in_group:该参数用于指定数据库中有几个日志组,默认为2个,因为有可能出现跨日志的大事务,一般来讲,建议使用 3~4 个日志组。
  13. innodb_log_buffer_size:该参数的作用是设置日志缓存的大小,一旦提交事务,则将该缓存池中的内容写到磁盘的日志文件上。该参数的设置在中等强度写入负载以及较短事务情况下,一般都可以满足服务器的性能要求。如果服务器负载较大,可以考虑加大该参数的值。一般缓存池中的内存每秒钟写到磁盘一次,所以设置较大会浪费内存空间,一般设置为 8MB~16MB 就足够了。可以参考 Innodb_os_log_written 的值,如果该值增加过快,可以适当的增加该参数的值。
  14. innodb_flush_log_at_trx_commit:表示何时将缓冲区的数据写入日志文件,并且将日志文件写入磁盘中。该参数有 3 个值,分别为 0、1 和 2。
    • 值为 0 时,表示每隔 1 秒将数据写入日志文件并将日志文件写入磁盘;
    • 值为 1 时,表示每次提交事务时将数据写入日志文件并将日志文件写入磁盘;
    • 值为 2 时,表示每次提交事务时将数据写入日志文件,每隔 1 秒将日志文件写入磁盘。

该参数的默认值为 1,是最安全最合理的值。为了保证事务的持久性和一致性,建议将该参数设置为 1。

参数设置的值要根据自己的实际情况来设置,并不是值越大越好,可能设置的数值太大体现不出优化效果,反而造成系统空间被占用,导致操作系统变慢。合理的配置参数可以提高 MySQL 服务器的性能。需要注意的是,配置完参数以后,需要重新启动 MySQL 服务配置才会生效。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342