1.mysql优化

[TOC]

1.mysql优化总览

1.执行计划

显示的信息有id,select_type,table,type,key,ref等信息

id:如果有子查询,ID的序号会递增(比如id会出现2了),在一组循环中id越大优先级越高,越早被执行

select_type:查询类型,可以理解为执行语句的类型,比如还可以update等。SIMPLE为简单查询,没有其他单位联合的查询,如果有其他单位一起查询,称之为组合查询

table:显示这一行的数据是关于哪张表的

⭐type:这是重要的列,显示连接使用了何种类型。从最好到最差的连接类型为const、eq_reg、ref、range、 indexhe和ALL,
   ⭐ ALL 扫描全表数据
    ⭐index 遍历索引
    range 索引范围查找
    index_subquery 在子查询中使用 ref
    unique_subquery 在子查询中使用 eq_ref
    ref_or_null 对Null进行索引的优化的 ref
    fulltext 使用全文索引
   ⭐ ref 使用非唯一索引查找数据
    eq_ref 在join查询中使用PRIMARY KEYorUNIQUE NOT NULL索引关联。
   ⭐ const 使用主键或者唯一索引,且匹配的结果只有一条记录。
    system const 连接类型的特例,查询的表为系统表。

    ALL最差(全表扫描)
    system(性能最好),const的特例:表仅有一行,平时基本不会出现,忽略不计
    const数据库最多匹配一行,最优化的,比如查询id为1的那行数据,const直奔id为1的那行,常用于PRIMARY索引的查询,参数rows为1就表示只扫描的一行

possible_keys:显示可能应用在这张表中的索引。如果为空,没有可能的索引。可以为相关的域从WHERE语句中选择一个合适的语句

⭐key: 实际使用的索引。如果为NULL,则没有使用索引。很少的情况下,MYSQL会选择优化不足的索引。这种情况下,可以在SELECT语句中使用USE INDEX(indexname)来强制使用一个索引或者用IGNORE INDEX(indexname)来强制MYSQL忽略索引

key_len:使用的索引的长度。在不损失精确性的情况下,长度越短越好

ref:显示索引的哪一列被使用了,如果可能的话,是一个常数

⭐rows:MYSQL认为必须检查的用来返回请求数据的行数

⭐Extra:关于MYSQL如何解析查询的额外信息。坏的例子是Using temporary和Using filesort,意思MYSQL根本不能使用索引,结果是检索会很慢
    Using index 使用覆盖索引
    Using where 使用了用where子句来过滤结果集
    Using filesort 使用文件排序,使用非索引列进行排序时出现,非常消耗性能,尽量优化。
                1.对于排序字段加索引 2.sort_buffer_size修改其值
    Using temporary 表示由于排序没有走索引、使用union、子查询连接查询、使用某些视图等原因,因此创建了一个内部临时表
    使用了临时表 sql优化的目标可以参考阿里开发手册

1.1 软件上

也就是sql的优化

简单比如索引,

1.查询语句的优化
2.优化子查询
3.使用索引
4.分解表
5.增加中间表
6.增加冗余字段
7.分析表,检查表,优化表

1.1 查询语句优化

我们常常使用explain(describe)分析执行查询语句的执行信息

desc select city,name,age from t where city='杭州' order by name desc limit 1000  ;
sql执行信息.jpg

查看执行key的信息 ,及rows查询行数来优化

1.2 优化子查询

在MySQL中,尽量使用JOIN来代替子查询.因为子查询需要嵌套查询,嵌套查询时会建立一张临时表,临时表的建立和删除都会有较大的系统开销,而连接查询不会创建临时表,因此效率比嵌套子查询高.

1.3 使用索引

索引是提高数据库查询速度最重要的方法之一,此处记录使用索引的三大注意事项:

  1. LIKE关键字匹配'%'开头的字符串,不会使用索引.
  2. OR关键字的两个字段必须都是用了索引,该查询才会使用索引.
  3. 使用多列索引必须满足最左匹配.

1.4 分解表

对于字段较多的表,如果某些字段使用频率较低,此时应当,将其分离出来从而形成新的表,

1.5 中间表

对于将大量连接查询的表可以创建中间表,从而减少在查询时造成的连接耗时.

1.6 增加冗余字段

类似于创建中间表,增加冗余也是为了减少连接查询.

1.7 分析表,,检查表,优化表

1. 分析表

使用 ANALYZE 关键字,如ANALYZE TABLE user;

  1. Op:表示执行的操作.
  2. Msg_type:信息类型,有status,info,note,warning,error.
  3. Msg_text:显示信息.

2. 检查表:

使用 CHECK关键字,如CHECK TABLE user [option]

option 只对MyISAM有效,共五个参数值:

  1. QUICK:不扫描行,不检查错误的连接.
  2. FAST:只检查没有正确关闭的表.
  3. CHANGED:只检查上次检查后被更改的表和没被正确关闭的表.
  4. MEDIUM:扫描行,以验证被删除的连接是有效的,也可以计算各行关键字校验和.
  5. EXTENDED:最全面的的检查,对每行关键字全面查找.

3. 优化表

使用OPTIMIZE关键字,如OPTIMIZE [LOCAL|NO_WRITE_TO_BINLOG] TABLE user;

LOCAL|NO_WRITE_TO_BINLOG都是表示不写入日志.,优化表只对VARCHAR,BLOB和TEXT有效,通过OPTIMIZE TABLE语句可以消除文件碎片,在执行过程中会加上只读锁.

对mysql进行大量增删改操作,磁盘上的空间没有被立即收回(数据空间、索引位),而是等待新的数据来填充空缺

optimize table tab_name

1.2 硬件优化

1.2-1 配置升级

1.配置多核心和频率高的cpu,多核心可以执行多个线程.

2.配置大内存,提高内存,即可提高缓存区容量,因此能减少磁盘I/O时间,从而提高响应速度.

3.配置高速磁盘或合理分布磁盘:高速磁盘提高I/O,分布磁盘能提高并行操作的能力.

1.2-2 优化数据库参数

优化数据库参数可以提高资源利用率,从而提高MySQL服务器性能.MySQL服务的配置参数都在my.cnf或my.ini,下面列出性能影响较大的几个参数.

  • key_buffer_size:索引缓冲区大小
  • table_cache:能同时打开表的个数
  • query_cache_size和query_cache_type:前者是查询缓冲区大小,后者是前面参数的开关,0表示不使用缓冲区,1表示使用缓冲区,但可以在查询中使用SQL_NO_CACHE表示不要使用缓冲区,2表示在查询中明确指出使用缓冲区才用缓冲区,即SQL_CACHE.
  • sort_buffer_size:排序缓冲区

1.2-3 分库分表

因为数据库压力过大,首先一个问题就是高峰期系统性能可能会降低,因为数据库负载过高对性能会有影响。另外一个,压力过大把你的数据库给搞挂了怎么办?所以此时你必须得对系统做分库分表 + 读写分离,也就是把一个库拆分为多个库,部署在多个数据库服务上,这时作为主库承载写入请求。然后每个主库都挂载至少一个从库,由从库来承载读请求。

分库分表.png

1.2-4 缓存集群

如果用户量越来越大,此时你可以不停的加机器,比如说系统层面不停加机器,就可以承载更高的并发请求。然后数据库层面如果写入并发越来越高,就扩容加数据库服务器,通过分库分表是可以支持扩容机器的,如果数据库层面的读并发越来越高,就扩容加更多的从库。但是这里有一个很大的问题:数据库其实本身不是用来承载高并发请求的,所以通常来说,数据库单机每秒承载的并发就在几千的数量级,而且数据库使用的机器都是比较高配置,比较昂贵的机器,成本很高。如果你就是简单的不停的加机器,其实是不对的。所以在高并发架构里通常都有缓存这个环节,缓存系统的设计就是为了承载高并发而生。所以单机承载的并发量都在每秒几万,甚至每秒数十万,对高并发的承载能力比数据库系统要高出一到两个数量级。所以你完全可以根据系统的业务特性,对那种写少读多的请求,引入缓存集群。具体来说,就是在写数据库的时候同时写一份数据到缓存集群里,然后用缓存集群来承载大部分的读请求。这样的话,通过缓存集群,就可以用更少的机器资源承载更高的并发。

1.3 查询优化

1.3-1 limit分页

select * 
from stu
where type = '2020'
order by reg_time
limit 1000,10


给type加上索引,确实能使查询效率变快
但是如果是 limit 1000000000,10
这也会变得很慢

方案

在前端数据浏览翻页,可以将上一页的最大值作为查询条件
select * 
from stu
where type = '2020'
and reg_time > '2020-11-24 11:18:00'
order by reg_time
limit 10

1.3-2 limit查改删

select * stu where stu_name = 'summit';

如果stu_name是唯一索引,可以这么写

select * stu where stu_name = 'summit' limit 1;
update stu set stu_name = 'summit' where id = '1' limit 1;
修改操作时,能确定只修改一条,加上limit 1,否则生产update写错,导致大量数据被修改;

1.3-3 超大分页怎么处理?

1.索引覆盖,要查询的所有字段都在索引中,所以速度会很快
select * from table where age > 20 limit 1000000,10
select * from table where id in (select id from table where age > 20 limit 1000000,10)
2.带上上一页的条件比如: id>上一页最大id

LIMIT偏移量大的时候,查询效率较低
可以记录上次查询的最大ID,下次查询时直接根据该ID来查询

1.3-4 优化WHERE子句

多数数据库都是从左往右的顺序处理条件的,把能够过滤更多数据的条件放到前面,把过滤少的条件放在后面

1.3-5 优化子查询

用关联查询替代
优化GROUP BY和DISTINCT
这两种查询据可以使用索引来优化,是最有效的优化方法
关联查询中,使用标识列分组的效率更高
如果不需要ORDER BY,进行GROUP BY时加ORDER BY NULL,MySQL不会再进行文件排序。
WITH ROLLUP超级聚合,可以挪到应用程序处理

1.3-6 优化UNION查询

UNION ALL的效率高于UNION

你可能感兴趣的:(1.mysql优化)