mysql系列【mysql优化完结篇】(面试必问)

前言

hello,大家好!博主上篇内容【mysql索引优化】 也是mysql优化的一部分,因为所以这一块相对来说内容比较多,所以单独抽取出来;大家都知道mysql优化是面试中的常客,也是重头戏,希望这篇内容能给到大家帮助

1、查找慢查询并定位慢查询

其中mysql的慢查询参数

  • slow_query_log 慢查询开启状态
  • slow_query_log_file 慢查询日志存放的位置(这个目录需要MySQL的运行帐号的可写权限,一般设置为MySQL的数据存放目录)
  • long_query_time 查询超过多少秒才记录

1、查看慢查询的相关参数

mysql> show variables like 'slow_query%';
+---------------------------+----------------------------------+
| Variable_name             | Value                            |
+---------------------------+----------------------------------+
| slow_query_log            | OFF                              |
| slow_query_log_file       | /mysql/data/localhost-slow.log   |
+---------------------------+----------------------------------+

mysql> show variables like 'long_query_time';
+-----------------+-----------+
| Variable_name   | Value     |
+-----------------+-----------+
| long_query_time | 10.000000 |
+-----------------+-----------+

2、设置方法

方法一:全局变量设置


-- 将 slow_query_log 全局变量设置为“ON”状态
mysql> set global slow_query_log='ON'; 

--设置慢查询日志存放的位置
mysql> set global slow_query_log_file='/usr/local/mysql/data/slow.log';
--查询超过1秒就记录
mysql> set global long_query_time=1;

方法二:配置文件设置

修改配置文件my.cnf,在[mysqld]下的下方加入
[mysqld]
slow_query_log = ON
slow_query_log_file = /usr/local/mysql/data/slow.log
long_query_time = 1

3、然后使用explain详细分析sql语句

2、选择合适的存储引擎

Mysql 中常用的两个引擎 MyISAMInnoDB

MyISAM
默认表类型(5.5之前),它是基于传统的ISAM(Indexed Sequential Access Method)类型(有索引的顺序访问方法),它是存储记录和文件的标准方法。不是事务安全的,而且不支持外键,如果表对事务要求不高,同时是以查询和添加为主的,我们考虑使用MyISAM,比如bbs中的发帖表,回复表,

InnoDB:mysql5.5之后默认的存储引擎,支持事务;支持外键;行锁;事务是他的最大特点。如果有大量的update和insert,建议使用InnoDB,特别是针对多个并发和QPS较高的情况。比如订单表,账号表。

InnoDB和MyISAM的区别

  • 事务 :
    InnoDB支持事务,MyISAM不支持事务
  • 外键 :
    InnoDB支持外键,MyISAM不支持外键
  • 全文索引
    InnoDB不支持全文索引,MyISAM支持
  • 业务
    InnoDB适合高并发业务,MyISAM适合查询比较多的业务

  • InnoDB支持行锁,但是是基于索引有效的情况,如果索引失效,InnoDB会默认行锁转变成表锁,MyISAM只支持表锁

3、mysql分区分表

在此之前得有一些原则

基本原则
设计数据库表的时候需要三大范式
是首先符合1N,才能满足2NF,进一步满是3NF

  • 1NF:即表的列的具有原子性,不可再分解,即列的信息,不烧分解.只要数据库是关系型数据库(mysql/oracle/db2/syshase/sql server),就自动的满足1NF.关系型数据库中是不允许分割列的。
  • 2NF:表中的记录是唯一的通常我们设计一个主键来实现
  • 3NF:即表中不要有元余数据,就是说,表的信息,如果能够按推导出来,就不应该单独的设计一个字段来存放.

优化
反3NF:没有冗余的数据库未必是最好的数据库,有时为了提高运行效率,就必须降低范式标准,适当保留冗余数据。具体做法是;在概念数据模型设计时遵守第三范式,降低范式标准的工作放到物理数据模型设计时考虑。降低范式就是增加字段,允许冗余。

  • 分区就是把一张表的数据分成N多个区块,这些区块可以在同一个磁盘上,也可以在不同的磁盘上
  • 分表从表面意思上看呢,就是把一张表分成N多个小表
  • 分表和表分区的目的就是减少数据库的负担,提高数据库的效率,通常点来讲就是提高表的增删改查效率。

mysql分区
partition,分区是将数据分段划分在多个位置存放,可以是同一块磁盘也可以在不同的机器。分区后,表面上还是一张表,但数据散列到多个位置了。程序读写的时候操作的还是大表名字,db自动去组织分区的数据。 下面看下语法👇

-- 创建表的时候添加分区
Create table table_name (定义)

Partition by 分区算法 (参数) 分区选项。

例如:Partition by key (id) partitions 5;
------------	
create table partition_1(
id int UNSIGNED not nul1 AUTO_INCREMENT, 
title varchar(255), PRIMARY KEY(id)
)engine=myisam
partition by key(id) partitions 5;

分区算法

MySQL提供4种分区算法: Key hash Listrange

参与分区的参数字段需要为主键的一部分。

mysql的分表
这个是真正的分表,一张表分成很多表后,每一个小表都是完正的一张表,都对应三个文件,一个.MYD数据文件,.MYI索引文件,.frm表结构文件。

分表又分为水平分表垂直分表

  • 水平分表
    mysql表数据一般达到百万级别,查询效率会很低,容易造成表锁,甚至堆积很多连接,直接挂掉;水平分表能够很大程度减少这些压力。

在这里插入图片描述

  • 垂直分表
    如果一张表中某个字段值非常多(长文本、二进制等),而且只有在很少的情况下会查询。这时候就可以把字段多个单独放到一个表,通过外键关联起来。

4、主从复制

  • 一台数据库支种的最大并发连接数是有限的,如果用户并发访问太多,一台服务器满足不要要求是就可以集群处理。mysql的集群处理技术最常用的就是读写分离,不过我们得先主从复制
  • 一个sql语句需要锁表,导致暂时不能使用读的服务,那么就很影响运行中的业务,使用主从复制,让主库负责写,从库负责读,这样,即使主库出现了锁表的情景,通过读从库也可以保证业务的正常运作。

MySQL复制过程分成三步:

  • MySQL的主从复制是一个异步的复制过程,数据将从一个MySQL数据库(Master)复制到另一个MySQL数据库(Slave)
  • 在Master和Slave之间实现整个主从复制的过程是由三个线程参与完成的。其中两个线程(SQL线程和IO线程)在Slave端,另一个线程(I/O线程)在Master端。
  • 要实现MySQL的主从复制,首先必须打开Master端的binlog记录功能,否则就无法实现。binlog: binary log,是主库中保存所有更新事件日志的二进制文件。因为整个复制过程实际上就是Slave从Master端获取binlog日志,然后在Slave上以相同顺序执行获取的binlog日志中的记录的各种SQL操作。

在这里插入图片描述

  1. master将改变记录到二进制日志(binary log)。这些记录过程叫做二进制日志事件,binary log events;
  2. slave将master的binary log events拷贝到它的中继日志(relay log);
  3. slave重做中继日志中的事件,将改变应用到自己的数据库中。MySQL复制是异步的且串行化的

5、使用各种缓存

说到缓存,可能大家就比较熟悉了,redis呀,query_cache等等

但是mysql8.0已经取消了查询缓存,相信也有一定的道理吧
包括mongodb这样的nosql数据库都可以为mysql减轻一定的压力,

6、你是怎样优化分页语句?

mysql中你的分页是这样写的么:
select column from table limit (page-1)*size,size;
其实如果数据量大这就必须要优化了

select column_name
from table as b inner join (
select id from table as a limit (page-1)*size 
) where a.id = b.id

上面就是简单的优化,因为这个limit 的第一个参数基数越大,查询时间就越长,这里靠主键索引能够起不小的作用呢

结言:欧了,以上两篇mysql优化内容算是告一段落了,希望我们能够在求职道路上披荆斩棘,职业生涯越走越远,也欢迎评论区留言 ,喜欢博文可以给个👍呦,也可以关注我【jar壳虫】,后续会有更多分享🎈🎈

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章