MySql高级-02:优化步骤以及优化方法【重点】

本教程引自黑马程序员MySQL视频:https://www.bilibili.com/video/BV1zJ411M7TB

第一章:优化SQL步骤

在应用程序开发过程中,由于前期数据量小,开发人员更注重功能上的实现。功能上线后随着数据量越来越大,有些SQL可能就会变得很慢,成为系统的瓶颈,这时候就需要对SQL就行系统的优化。

本章主要介绍应该从何处以及怎么快速定位SQL问题。

1.1 查看SQL执行频率

MySQL客户端链接成功后,通过命令来查看服务器的统计结果(从上次启动至今)。可以查看本次会话(session)以及全局(global)的统计,默认是session。
目的是查看应用程序是以查询为主还是以增删改为主,为sql优化提供借鉴。

语法如下:

#查看本次会话
show status like 'Com_______';

#查看全局
show global status like 'Com_______';

在这里插入图片描述

也可以针对InnoDB存储引擎进行统计,语法如下:

SHOW GLOBAL STATUS LIKE 'Innodb_row_%';

在这里插入图片描述
参数解释:

参数 含义
Com_select 执行select操作的次数,一次查询只累加1。
Com_insert 执行insert操作的次数,批量插入也只累加1
Com_update 执行update操作的次数
Com_delete 执行delete操作的次数
Innodb_rows_read select查询返回的行数
Innodb_rows_inserted 执行insert操作插入的行数
Innodb_rows_updated 执行update操作更新的行数
Innodb_rows_deleted 执行delete操作删除的行数

1.2 定位低效率SQL

可以通过以下两种方式定位执行效率较低的SQL语句。

  • 慢查询日志:
    用–log-slow-queries[=file_name]选项启动时,mysqld写一个包含所有执行时间超过long_query_time秒的SQL语句的日志文件,此方式在后面的笔记又详细记录,这里先跳过。
  • show processlist:
    慢查询日志在查询结束以后才记录,所以并不能实时的定位问题,可以使用show processlist命令查看当前MySQL在进行的线程,包括线程的状态、是否锁表等,可以实时地查看SQL的执行情况,同时对一些锁表操作进行优化

在这里插入图片描述
在这里插入图片描述

1.3 explain分析执行计划

找到查询效率较低的SQL语句后,可以通过explain或者desc命令获取MySQL如何执行SELECT语句的信息,包括在SELECT语句执行过程中表如何连接和连接的顺序。
在这里插入图片描述

1.3.1 环境准备

先创建三张表在这里插入图片描述

#创建角色表
CREATE TABLE `t_role` (
  `id` varchar(32) NOT NULL,
  `role_name` varchar(255) DEFAULT NULL,
  `role_code` varchar(255) DEFAULT NULL,
  `description` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_role_name` (`role_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

#创建用户表
CREATE TABLE `t_user` (
  `id` varchar(32) NOT NULL,
  `username` varchar(45) NOT NULL,
  `password` varchar(96) NOT NULL,
  `name` varchar(45) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_user_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

#创建用户和角色关系表
CREATE TABLE `user_role` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` varchar(32) NOT NULL,
  `role_id` varchar(32) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `fk_user_id` (`user_id`),
  KEY `fk_role_id` (`role_id`),
  CONSTRAINT `fk_ur_role_id` FOREIGN KEY (`role_id`) REFERENCES `t_role` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `fk_ur_user_id` FOREIGN KEY (`user_id`) REFERENCES `t_user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

#插入用户数据
insert into t_user (id,username,password,name)
values('1','super','$2Es33eEkl4ckjti$#sweEKL8347EC3434Re','超级管理员');
insert into t_user (id,username,password,name)
values('2','admin','$2Es33eEkl4ckjti$#sweEKL8347EC3434Re','系统管理员');
insert into t_user (id,username,password,name)
values('3','itcast','$2Es33eEkl4ckjti$#sweEKL8347EC3434Re','test02');
insert into t_user (id,username,password,name)
values('4','stu1','$2Es33eEkl4ckjti$#sweEKL8347EC3434Re','学生1');
insert into t_user (id,username,password,name)
values('5','stu2','$2Es33eEkl4ckjti$#sweEKL8347EC3434Re','学生2');
insert into t_user (id,username,password,name)
values('6','t1','$2Es33eEkl4ckjti$#sweEKL8347EC3434Re','老师1');

#插入角色表
insert into t_role (id,role_name,role_code,description)
values('5','学生','student','学生');
insert into t_role (id,role_name,role_code,description)
values('7','老师','teacher','老师');
insert into t_role (id,role_name,role_code,description)
values('8','教学管理员','teachmanager','教学管理员');
insert into t_role (id,role_name,role_code,description)
values('9','管理员','admin','管理员');
insert into t_role (id,role_name,role_code,description)
values('10','超级管理员','super','超级管理员');

#插入关系表
insert into user_role(id,user_id,role_id)values(null,'1','5'),(null,'1','7'),(null,'2','8'),(null,'3','9'),(null,'4','8'),(null,'5','10');

1.3.2 explain之id

id字段是select查询的序列号,表示的是查询执行表的顺序。有以下三种情况:

1. id相同,表示加载表的顺序是从上到下

EXPLAIN SELECT * FROM t_user u,t_role r,user_role ur WHERE r.`id`=ur.`role_id` AND u.`id`=ur.`user_id`;

在这里插入图片描述
2. id不相同,值越大优先级越高。

EXPLAIN SELECT * FROM t_role WHERE id = (SELECT role_id FROM user_role WHERE user_id IN (SELECT id FROM t_user WHERE username='stu1'))

在这里插入图片描述
3. 前两种情况的结合,Id有相同的有不同的,Id大的优先执行,碰到相同的就从上往下依次执行。

1.3.3 explain之select_type

表示select的类型,常见的值有以下几个:

select_type 含义
SIMPLE 简单的select查询,查询中不包含子查询或UNION
PRIMARY 查询中若包含任何复杂的子查询,最外层查询标记为该标识
SUBQUERY 在select或where列表中包含了子查询
DERIVED 在from列表中包含的子查询,被标记为 DERIVED(衍生),MySQL会递归执行这些子查询,把结果放到临时表中
UNION 若第二个select出现在union之后,则被标记为UNION;若UNION包含在FROM子句的子查询中,外层select将被标记为:DERIVED
UNION RESULT 从UNION表获取结果的SELECT

上表中,select_type从上到下,效率越来越低。

1.3.4 explain之type

type显示的是访问类型,是较为重要的一个指标,可取值为:

type 含义
NULL MySQL不访问任何表,索引,直接返回结果
system 表只有一行记录(等于系统表),这是const类型的特例,一般不会出现
const 表示通过索引一次就找到了,const用于比较primary key或者unique索引。因为只匹配一行数据所以很快。如将主键索引置于where语句中,MySQL就能将该查询转换为一个常量。
eq_ref 类似于ref,区别在于使用的是唯一索引,使用主键的多表关联查询,关联查询出的记录只有一条。常见于主键或唯一索引扫描
ref 非唯一索引扫描,返回匹配某个单独值得所有行。本质上也是一种索引访问,返回所有匹配某个单独值得所有行(多个)
range 只检索给定返回得行,使用一个索引来选择行。where之后出现between,<,>,in等范围搜索
index index与all得区别为index类型只是遍历了索引树,通常比all快,all是遍历数据文件
all 将遍历全表以找到匹配得行
结果从好到坏以此是:
NULL > system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL

一般来说,优化语句得时候能达到ref或者range级别就可以了。

1.3.5 explain之key和rows

possible_keys:显示可能应用在这张表得索引,一个或多个。查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询实际使用。
key:实际使用得索引,如果为NULL,则没有使用索引。
key_len:表示索引使用得字节数,该值为索引字段最大可能长度。在不损失精确性的情况下,长度越短越好。
rows:扫描的行数。

1.3.6 explain之extra

前面几个字段中没出现得,都会出现在extra中。

extra 含义
Using filesort 说明mysql会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取。mysql中无法利用索引完成的排序操作成为“文件排序”。出现这个就尽可能的优化。
Using temporary 使用了临时表保存了中间结果,mysql在对查询结果排序时使用临时表。常见于order by和group by。出现这个就赶紧优化。
Using index 表示相应的select操作中使用了覆盖索引,避免访问了表的数据行,效率很好;

1.4 show profile 分析SQL

MySQL从5.0.37版本开始增加了对show profiles和show profile语句的支持,show profiles能够在做SQL优化时帮助我们了解时间都耗到哪里去了。

通过have_profiling参数,可以看到当前MySQL是否支持profile;
在这里插入图片描述
默认profiling是关闭的,可以通过set语句在Session级别开启profiling;
在这里插入图片描述
0代表关闭

#开启profiling
set profiling=1;

接下来可以进行一系列操作,比如以下操作,然后通过show profiles命令来查看执行时间。

select * from orderdp_shop_data where operation_type like '%VISIT%';
show profiles;

在这里插入图片描述

show profile for query 58;

在这里插入图片描述

TIP:
	Sending data 状态标识MySQL线程开始访问数据行并把结果返回给客户端,而不仅仅是返回数据到客户端。由于是在Sending data下,MySQL线程往往需要做大量的磁盘读取操作,所以往往该状态是查询中耗时最长的状态。
	查询的结果中出现以下状态,就需要注意了,尽量去优化SQL:
	1.converting HEAP to MyISAM:查询结果太大,内存不够用了,需要借用磁盘空间。
	2.Creating tmp table:创建临时表
	3.Copying to tmp table on disk:把内存中临时表文件复制到磁盘,危急!!
	4.locked:出现了锁

1.5 trace分析优化器执行计划【了解】

MySQL5.6提供了对SQL的跟踪trace,通过trace文件能够进一步了解为什么优化器选择A计划,而不是选择B计划。
打开trance,设置格式为JSON,并设置trace最大能够使用的内存大小,避免解析过程中因为默认内存过小而不能够完整展示。

set optimizer_trace="enabled=on",end_markers_in_json=on;
set optimizer_trace_max_mem_size=1000000;

执行SQL语句

SELECT * FROM tb_item WHERE id >=364479 LIMIT 100000000;

最后,检查information_schema.optimizer_trace就可以知道MySQL是如何执行SQL的;

select * from information_schema.optimizer_trace\G;

在这里插入图片描述

第二章:索引的使用

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

2.1 准备环境

创建tb_seller表

create table tb_serller(
sellerid varchar(100),
name varchar(100),
nickname varchar(50),
password varchar(60),
status varchar(1),
address varchar(100),
createtime datetime,
primary key(sellerid)
) engine=innodb default charset=utf8mb4;

insert into tb_seller(sellerid,name,nickname,password,status,address,createtime) 
values ('alibaba','阿里巴巴','阿里小店','$2a$10$Lcbp1MmF89e0lxig7CyJ1O2A3vu7GRT9aAKCy/FGyYjmvjnkaiqkS','1','北京市',now()),
('baidu','百度科技有限公司','百度小店','$2a$10$Lcbp1MmF89e0lxig7CyJ1O2A3vu7GRT9aAKCy/FGyYjmvjnkaiqkS','1','北京市',now()),
('huawei','华为科技有限公司','华为小店','$2a$10$Lcbp1MmF89e0lxig7CyJ1O2A3vu7GRT9aAKCy/FGyYjmvjnkaiqkS','0','北京市',now()),
('itcast','传智播客教育科技有限公司','传智播客','$2a$10$Lcbp1MmF89e0lxig7CyJ1O2A3vu7GRT9aAKCy/FGyYjmvjnkaiqkS','1','北京市',now()),
('itheima','黑马程序员','黑马程序员','$2a$10$Lcbp1MmF89e0lxig7CyJ1O2A3vu7GRT9aAKCy/FGyYjmvjnkaiqkS','0','北京市',now()),
('luoji','罗技科技有限公司','罗技小店','$2a$10$Lcbp1MmF89e0lxig7CyJ1O2A3vu7GRT9aAKCy/FGyYjmvjnkaiqkS','1','北京市',now()),
('oppo','OPPO科技有限公司','OPPO官方旗舰店','$2a$10$Lcbp1MmF89e0lxig7CyJ1O2A3vu7GRT9aAKCy/FGyYjmvjnkaiqkS','0','北京市',now()),
('ourpalm','掌趣科技股份有限公司','掌趣小店','$2a$10$Lcbp1MmF89e0lxig7CyJ1O2A3vu7GRT9aAKCy/FGyYjmvjnkaiqkS','1','北京市',now()),
('qiandu','千度科技','千度小店','$2a$10$Lcbp1MmF89e0lxig7CyJ1O2A3vu7GRT9aAKCy/FGyYjmvjnkaiqkS','2','北京市',now()),
('sina','新浪科技有限公司','新浪官方旗舰店','$2a$10$Lcbp1MmF89e0lxig7CyJ1O2A3vu7GRT9aAKCy/FGyYjmvjnkaiqkS','1','北京市',now()),
('xiaomi','小米科技','小米官方旗舰店','$2a$10$Lcbp1MmF89e0lxig7CyJ1O2A3vu7GRT9aAKCy/FGyYjmvjnkaiqkS','1','西安市',now()),
('yijia','宜家家居','宜家家居旗舰店','$2a$10$Lcbp1MmF89e0lxig7CyJ1O2A3vu7GRT9aAKCy/FGyYjmvjnkaiqkS','1','北京市',now());

#创建复合索引
create index idx_seller_name_sta_addr on tb_seller(name,status,address);

2.2 避免索引失效

1 全值匹配
对索引中所有列都指定具体值。
该情况下,索引生效,执行效率高

explain select * from tb_seller where name='小米科技' and status='1' and address='北京市'\G;

在这里插入图片描述
2 最左前缀法则
如果是多列索引,要遵守最左前缀法则。指的是查询从索引的最左前列开始,并且不跳过中间的列,如果所有的列都用到了,顺序乱了也没问题的。

遵守最左前缀法则,走索引。
在这里插入图片描述
违反最左前缀法则,不走索引。
在这里插入图片描述
上图中最后一个虽然有索引,其实是只有name列使用了索引,address字段并没有使用索引,通过索引长度就可以看出来,和只查询name的长度是一样的。

3 范围查询
范围查询,右边的列不能使用索引。
在这里插入图片描述

上图中第二条语句,name和status使用了索引,但是address没用到索引

4. 不要再索引列上进行运算操作,否则索引失效
5.字符串不加单引号,索引将失效
6.尽量使用覆盖索引,避免select *
覆盖所以就是只查询建立索引的字段。
7.or会导致索引失效
在这里插入图片描述
8.以%开头的Like查询,会导致索引失效
这种情况可以使用覆盖索引解决。
在这里插入图片描述9.如果MySQL评估使用全表扫描更快的话,那么就会放弃使用索引
例如,在某个字段上创建了索引,而这个字段的值高度集中,那么where语句使用该字段的时候,MySQL可能会放弃索引。比如在上面的表中的address创建索引,查询address等于北京的,总共12条记录,北京就占了11条,这种情况下使用索引没有全盘扫描快,MySQL可能就放弃使用索引了。

10.Is NULL、Is NOT NULL 有时索引失效
与第9点类似,都是MySQL自动评估使不使用索引的。
如果NULL值比较多,那么Is NOT NULL就走索引,而Is NULL不走索引;
如果非NULL值比较多,那么Is NULL就走索引,而Is NOT NULL不走索引;

11. in走索引,not in 不走索引

12.单列索引和复合索引
尽量使用复合索引,少使用单列索引。
在这里插入图片描述
创建多个单列索引,假如where语句中把创建索引的列都用到了,那么MySQL也只会选择其中最优的一个索引使用,不会使用全部索引,而复合索引会将所有的索引都用到。

第三章:SQL优化

3.1 order by 优化

排序有两种方式:文件排序(Using filesort)和索引排序(Using index),索引排序的效率要高于文件排序。

  • 如果排序的字段没有索引的话就会走文件排序。
  • 多字段排序,order by后面字段的顺序要和创建复合索引时字段的顺序保持一致,否则也会出现文件排序。
  • 多字段排序,要么全部降序,要么全部升序,否则会出现文件排序。

尽量使用索引排序,但是有时文件排序也是无法避免的,如果出现文件排序怎么去优化呢?看下图:
在这里插入图片描述

3.2 group by 优化

由于group by实际上页同样会进行排序操作,所以在group by的实现过程中,与order by一样页可以利用到索引。
在这里插入图片描述
由上图可以看出,优化后没有使用文件排序了,但是依然使用了临时表,这种情况下可以对group by后面的字段创建索引。
在这里插入图片描述

3.3 嵌套查询的优化

子查询尽量使用连接替代。
在这里插入图片描述

3.4 优化or条件

在这里插入图片描述
虽然可以通过创建单列索引完成优化,但是更建议使用union替换or。就算通过or查询的字段都有索引通常也没有使用union的效率高,通过explain执行计划中的type字段就可以看出来。

在这里插入图片描述
在这里插入图片描述

3.5 分页查询优化

可以在索引列(比如主键)上完成分页操作,然后根据索引列关联查询其他需要的数据。
在这里插入图片描述

3.6 使用SQL提示

SQL提示,是优化数据库的一个重要手段,就是在SQL语句中加入一些认为的提示来达到优化操作的目的。

3.6.1 user index

在查询语句表名的后面,添加use index来提供MySQL去参考的索引列表,就可以让MySQL不再考虑其他可用的索引。

#创建name列索引
create index idx_seller_name on tb_seller(name);

查看MySQL默认使用的索引

explain select * from tb_seller where name='小米科技';

在这里插入图片描述
上图可以看出,MySQL判定可能用到的索引有两个,最终使用的是复合索引。
这时我们可以用user index 关键字让MySQL优先考虑指定的索引(非强制性)

EXPLAIN SELECT * FROM tb_seller USE INDEX(idx_seller_name) WHERE NAME='小米科技';

在这里插入图片描述
这时,MySQL判定可能用到的索引以及实际使用的索引都是我们指定的索引(非强制性,有时MySQL也会不使用我们指定的索引)。

3.6.2 ignore index

让MySQL忽略一个或多个索引

EXPLAIN SELECT * FROM tb_seller ignore INDEX(idx_seller_name_sta_addr) WHERE NAME='小米科技';

在这里插入图片描述

3.6.3 force index

强制MySQL使用一个只顶你的索引。

#为address列创建一个单列索引
create index idx_seller_address on tb_seller(address);

查询地址,看MySQL会不会使用刚刚创建的索引:

EXPLAIN SELECT * FROM tb_seller WHERE address='北京市';

在这里插入图片描述
上图可知,MySQL判定可能用到的所以就是我们刚刚创建的索引,但是实际上并未使用索引。因为表中共有12条数据,而“北京市”就占了11条,加上检索索引等,使用索引比全表扫描效率低,所以MySQL就没有使用索引。如果查询语句里把“北京市”换成“西安市”就会用到索引了,如下:
在这里插入图片描述
但是,我们可以通过force index关键字强制MySQL使用索引,如下图:
在这里插入图片描述

3.7 查询缓存优化

3.7.1 查看缓存配置

1. 查看当前的MySQL数据库是否支持查询缓存:

show variables like 'have_query_cache';

在这里插入图片描述

2. 查看当前MYSQL数据库是否开启了查询缓存:

SHOW VARIABLES LIKE 'query_cache_type';

在这里插入图片描述
默认是OFF关闭状态

3. 查看查询缓存的占用大小:

SHOW VARIABLES LIKE 'query_cache_size';

单位是字节 除以(1024*1024)就是M了
在这里插入图片描述

4. 查询缓存状态

show status like 'Qcache%';

在这里插入图片描述
各个参数定义如下:
在这里插入图片描述

3.7.2 开启查询缓存

MySQL的查询缓存默认是关闭的,需要手动配置参数query_cache_type来开启。该参数有三个可取值:

含义
OFF 或 0 查询缓存功能关闭
ON 或 1 查询缓存功能开启。如果显示指定SQL_NO_CACHE,则不予缓存
DEMAND 或 2 查询缓存功能按需进行,显式指定SQL_CACHE的select语句才会缓存,其他的均不予缓存

在my.cnf配置中增加以下配置,然后重启MySQL服务

query_cache_type=1

在这里插入图片描述
在这里插入图片描述
测试以下开启缓存的效果,执行一条比较耗时的语句,对比第一次执行和第二次执行的时间。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
以上三张图可以看出查询缓存生效了,后面执行查询的时间都远远小于第一次执行查询的时间,而且Qcache_inserts字段证明缓存已有2条查询语句被添加到查询缓存中(因为我执行了两次 一次有空格一次没空格)。

3.7.3 查询缓存失效的情况

1)SQL语句不一致的情况,要命中查询缓存,查询的SQL语句必须一致,多个空格或少个空格都不行。

2)SQL语句包含一些不确定因素时,则不会缓存。如:now(),current_date(),curdate(),rand(),uuid()等。
3)不使用任何表得查询语句:

select 'A'

4)查询MySQL自带得表时,不会走缓存
5)在存储得函数,触发器或事件得主体内执行得查询。
6)表数据发生变化时,比如增加数据,删除数据或修改数据以及对表执行TRUNCATE TABLE、ALTER TABLE、DROP TABLE等。

3.8 内存管理及优化

3.8.1 内存优化原则

1)在保证操作系统及其他应用程序足够用得前提下,将尽量多的内存分配给MySQL做缓存。
2)MyISAM存储引擎得数据文件读取依赖于操作系统自身的IO缓存,因此如果有MyiSAM表,就要预留更多的内存给操作系统做IO缓存。
3)排序区、链接区等缓存是分配给每个数据库会话(session)专用的,其默认值的设置要根据最大连接数合理分配,如果设置太大,不但浪费资源,而且在并发连接较高时,会导致物理内存耗尽。

3.8.2 MyISAM 内存优化(了解)

myisam存储引擎使用key_buffer缓存索引块,加速myisam索引的读写速度。对于myisam表的数据块,mysql没有特别的缓存机制,完全依赖于操作系统的IO缓存。

key_buffer_size
key_buffer_size决定MyISAM索引缓存块的大小,直接影响到MyISAM表的存取效率。可以在MySQL参数文件中设置key_buffer_size的值,对于一般的MyISAM数据库,建议至少将1/4可用内存分配给key_buffer_size。
在my.cnf中做如下配置。

key_buffer_size=512M

read_buffer_size
如果需要经常顺序扫描myisam表,可以通过增大read_buffer_size的值来改善性能。但需要注意的时read_buffer_size时每个session独占的,如果默认值设置太大,就会造成内存浪费。

read_rnd_buffer_size
如果需要做排序的myisam表的查询,如带有order by字句的sql,设当增加read_rnd_buffer_size的值,可以改善此类sql的性能。但需要注意的是read_rnd_buffer_size是每个session独占的,如果默认值设置太大,就会造成内存浪费。

3.8.2 InnoDB 内存优化(重点)

innodb用一块内存区做IO缓冲池,该缓存池不仅用来缓存innodb的索引块,而且也用来缓存innodb的数据块。

innodb_buffer_pool_size
该变量决定了innodb存储引擎表数据和索引数据的最大缓存区大小。在保证操作系统及其他程序有足够内存可用的情况下,innodb_buffer_pool_size的值越大,缓存命中率就越高,访问InnoDB表需要的IO就越少,性能也就越高。

innodb_buffer_pool_size=512M

innodb_log_buffer_size
决定了innodb重做日志缓存的大小,对于可能产生大量更新记录的大事务,增加innodb_log_buffer_size的大小,可以避免innodb在事务提交前就执行不必要的日志写入磁盘操作。

 innodb_log_buffer_size=10M

3.9 MySQL并发参数的调整

在MySQL中,控制并发连接和线程的主要参数包括max_connections、back_log、thread_cache_size、table_open_cache.

3.9.1 max_connections

采用max_connections控制允许连接到MySQL数据库的最大数量,默认值是151。如果状态变量connection_errors_max_connections不为零,并且一直增长,则说明不断有连接请求因数据库连接数以达到最大值而失败,这时可以考虑增大max_connections的值。
MySQL最大可支持的连接数,取决于很多因素,包括操作系统平台的线程库的质量、内存大小、每个连接的负荷、CPU的处理速度、期望的响应时间等。在linux平台下,性能好的服务器支持500-1000个连接不是难事,需要根据服务器性能进行评估设定。
查看默认值:

show variables like 'max_connections';

3.9.2 back_log

back_log参数控制MySQL监听TCP端口时设置的积压请求栈大小。如果MySQL的连接数达到max_connections时,新来的请求将会被存在堆栈中,以等待某一连接释放资源,该堆栈的数量即back_log。如果等待连接的数量超过back_log,将不被授予连接资源,会直接报错。5.6.6版本之前默认值为50,之后版本的默认值为50+(max_connections/5),但最大不超过900。
如果需要数据库在较短的时间内处理大量的连接请求,可以考虑适当增大back_log的值。

查看默认值:

show variables like 'back_log';

3.9.3 table_open_cache

该参数用来控制所有SQL语句执行线程可打开表缓存的数量,而在执行SQL语句时,每一个SQL执行线程至少要打开1个表缓存。该参数的值应该根据设置的最大连接数max_connections以及每个连接执行关联查询中涉及的表的最大数量来是定,公司如下:

max_connections * N;

查看默认值:

show variables like 'table_open_cache';

3.9.4 thread_cache_size

为了加快连接数据库的速度,MySQL会缓存一定数量的客户服务线程以备用,通过参数thread_cache_size可控制MySQL缓存客户服务线程的数量
查看默认值:

show variables like 'thread_cache_size';

3.9.5 innodb_lock_wait_timeout

该参数时用来设置InnoDB事务等待行锁的时间,默认是50ms,可以根据需要进行动态设置。对于需要快速反馈的业务系统来说,可以将行锁的等待时间调小,以避免事务长时间挂起;对于后台运行的批量处理程序来说,可以将行锁的等待时间调大,以避免发生大的回滚操作。
查看默认值:

show variables like 'innodb_lock_wait_timeout';

猜你喜欢

转载自blog.csdn.net/hpp3501/article/details/120704773
今日推荐