show variables like 'max_connections'
-- max_connections 151
install plugin rpl_semi_sync_master soname 'semisync_master.so';
show variables like '%semi_sync%'
-- 默认关闭,需要手动开启
show variables like '%gtid_mode%'
-- gtid_mode OFF
-- 默认关闭需要手动开启
3. 分表:垂直分表、水平分表
4. 分库:垂直分库、水平分库
开启慢查询日志会消耗性能
-- 慢查询配置
show variables like 'slow_query%';
-- 多长时间的查询才叫慢查询
show variables like 'long_query%';
mysql慢日志分析工具
mysqldumpslow --help
whereis mysqldumpslow
https://dev.mysql.com/doc/refman/5.7/en/show-profile.html
select @@profiling;
set @@profiling=1;
如果能确定长度,就不要定义定长的字段,给默认值也不要允许空值。
存非文本字段,应该存储地址。而不是存储编码。仅量和业务表做拆分。
对于字段很多的表,对字段进行拆分。
也可以利用字段冗余来避免join,提升查询性能。
历史表:增长速度快。按照时间维度区分。按年月划分为12个区。
更详细的explain:format=JSON
explain format=JSON select t.tname from teacher t group by tname;
https://dev.mysql.com/doc/refman/5.7/en/explain-output.html
drop table if exists course;
create table course(
id int(3) default null,
cname varchar(20) default null,
tid int(3) default null
) engine = InnoDB default charset = utf8mb4;
drop table if exists teacher;
create table teacher(
tid int(3) default null,
tname varchar(20) default null,
tcid int(3) default null
) engine = InnoDB default charset = utf8mb4;
drop table if exists teacher_contact;
create table teacher_contact(
tcid int(3) default null,
phone varchar(20) default null
) engine = InnoDB default charset = utf8mb4;
insert into course values(1,'java','1');
insert into course values(2,'jvm','1');
insert into course values(3,'mysql','2');
insert into course values(4,'c#','2');
insert into teacher values(1,'whx',1);
insert into teacher values(2,'huathy',2);
insert into teacher_contact values(1,'QQ12341234');
insert into teacher_contact values(2,'TEL123123123');
explain select * from teacher_contact tc where tcid = (
select t.tcid from teacher t where t.tid = (
select c.tid from course c where c.cname = 'jvm'
)
)
# 查询顺序从大到小
id|select_type|table|partitions|type|possible_keys|key|key_len|ref|rows|filtered|Extra |
--+-----------+-----+----------+----+-------------+---+-------+---+----+--------+-----------+
1|PRIMARY |tc | |ALL | | | | | 2| 50.0|Using where|
2|SUBQUERY |t | |ALL | | | | | 2| 50.0|Using where|
3|SUBQUERY |c | |ALL | | | | | 4| 25.0|Using where|
explain select * from teacher t
left join teacher_contact tc on t.tcid = tc.tcid
left join course c on t.tid = c.tid
where c.id = 2 or tc.tcid = 3;
# id相同,则从上到下依次访问
id|select_type|table|partitions|type|possible_keys|key|key_len|ref|rows|filtered|Extra |
--+-----------+-----+----------+----+-------------+---+-------+---+----+--------+--------------------------------------------------+
1|SIMPLE |t | |ALL | | | | | 2| 100.0| |
1|SIMPLE |tc | |ALL | | | | | 2| 100.0|Using where; Using join buffer (Block Nested Loop)|
1|SIMPLE |c | |ALL | | | | | 4| 100.0|Using where; Using join buffer (Block Nested Loop)|
小表驱动大表:关联查询会产生临时表,应优先查询表数据少的表。
explain select t.* from (
select * from teacher where tid =1
union
select * from teacher where tid =2
) t
type 针对单表的访问方法
链接类型:从左到右,性能越来越差
system > const > eq_ref > ref > range > index > ALL
在Memory或MyISAM存储引擎中,只能查询到一条记录。
在join中被驱动的表,是通过唯一索引去访问的。
alter table teacher_contact add primary key (tcid);
explain select t.* from teacher t,teacher_contact tc where t.tcid = tc.tcid;
alter table teacher add index idx_teacher_tcid(tcid);
explain select t.* from teacher t where t.tcid = 1;
alter table teacher add index idx_teacher_tid(tid);
explain select t.* from teacher t where t.tid < 3;
explain select t.* from teacher t where t.tid between 1 and 2;
explain select t.* from teacher_contact t where t.tcid in (1,2)
explain select t.tid from teacher t where t.tid
explain select * from course t where t.cname = 'huathy'
possible_keys、key
possible_keys:可能使用到的索引。
key:实际使用的索引。
有没有可能possible_keys是空的而实际key有值?有可能。基于成本的优化器会存在,覆盖索引和索引条件下推的情况。
使用的索引长度。
-- username varchar(255) null,
-- utf8mb3 一个字符占3个字节 255 * 3 = 765 + 2(varchar变长) + 1(null可以为空)
-- utf8mb4 一个字符占4个字节 1020 * 4 = 765 + 2(varchar变长) + 1(null可以为空)
const 表示使用参数为常量
InnoDB预读行数不太准确,而MyISAM统计较准。
MyISAM记录了我们的数据总行数。
如果返回行数与需要的结果相差太大,说明SQL需要优化。
数据库:Server层 == 存储引擎层(InnoDB)
如果filtered为100表示返回数据都是Server层所需要的。而如果值很低,说明SQL需要优化。
Extra 额外的信息
执行计划给出的额外信息。
select 查询的字段,刚好在索引中。就不需要回表操作。
存储引擎返回的数据不全是客户端所需要的,需要在Server层进行过滤。
索引条件下推。本来无法利用索引。但某些条件下可以将需要查询的条件下推到存储引擎。先让存储引擎进行过滤。
得到最终需要使用临时表来存储数据。eg:在非索引字段上去重,在非索引字段上分组。
select * from user_innodb limit 4000000,10; -- 4秒
select * from user_innodb where id > 4000000 limit 10; -- 0.1秒
熔断降级。业务分流。流量削峰。
或者更换非关系的数据库,eg:Redis、MongoDB。
show full processlist;
show status;
show engine innodb status;
MySQL中文网站:https://mysql.net.cn/doc/refman/8.0/en/