mysql优化

mysql优化_第1张图片

前言:

Io瓶颈和cpu瓶颈都会导致数据库活跃连接数增加,可进而会达到数据库承载活跃连接数的阈值。
IO瓶颈

  1. 磁盘IO:热点数据太多,数据库缓存放不下,查询时会产生大量的IO,降低查询速度
  2. 网络IO:请求的数据太多,网络带宽不够

cpu瓶颈

  1. sql问题
  2. 单表数据量太大,查询时扫描的行太多,sql效率低,cpu率先出现瓶颈

软件优化:

先根据慢查询,查找到运行比较慢的sql:
可以根据explain或者describe 分析一条查询语句的执行信息。将日志打开。

1.语句方面:

  • 可通过开启慢查询日志来找出较慢的 SQL
  • 不做列运算,SELECT id WHERE
    age+1=10,任何对列的操作都将导致表扫描,它包括数据库教程函数、计算表达式等等,查询时要尽可能将操作移至等号右边
  • sql 语句尽可能简单:一条 sql 只能在一个 cpu 运算;大语句拆小语句,减少锁时间;一条大sql 可以堵死整个库
  • 不 select *
  • OR改写成IN:OR的效率是 n 级别,IN的效率是 log(n) 级别;
  • 使用同类型进行比较 ;
  • join代替子查询;
  • or 的查询尽量用 union 代替(Innodb);
  • 应尽量避免在 where 子句中使用!=或<>操作符
  • 只需要一条记录的情况下使用limit 1
  • 尽量避免在 WHERE 子句中使用 != 或 <> 操作符,否则将引擎放弃使用索引而进行全表扫描

2.索引方面:

  • 索引并不是越多越好,要根据查询有针对性的创建,考虑在 WHERE 和 ORDER BY

考虑是否是索引失效:
①where字句使用is null或者is not null,not existnot in或不匹配的数据类型或使用函数都会导致索引失效
②对于多列索引,只有查询条件中使用了这些字段中第1个字段时,索引才会被使用
③查询条件中只有OR关键字,且OR前后的两个条件中列都是索引时,查询中才会使用索引。否则,查询将不使用索引。
④如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引;

  • like % 在前面用不到索引;
  • 索引多,写会变慢;
  • EXPLAIN是索引还是全表扫 ;
  • 值分布很稀少的字段不适合建索引,性别不建;
  • or关键字的两个字段都必须是用了索引,该查询语句才会用索引;
  • 多列索引必须满足最左匹配

3.字段方面:

  • 字段 用TINYINT,SMALLINT ,如果非负则加上 UNSIGNED
  • 单表20 以内
  • 避免用null字段,很难查询优化且占用额外索引空间
  • 整型IP ,使用枚举或整数代替字符串类型
  • TIMESTAMP 代替datestamp

比如:
查询第20条到第30条数据的sql是:select * from table limit 20,30; ->对应我们的需求就是查询第三页的数据:select * from table limit (3-1)*10,10;
4.引擎方面:
MyISAM 引擎是 MySQL 5.1 及之前版本的默认引擎,它的特点是:

  • 不支持行锁,读取时对需要读到的所有表加锁,写入时则对表加排它锁
  • 不支持事务
  • 不支持外键
  • 不支持崩溃后的安全恢复
  • 在表有读取查询的同时,支持往表中插入新纪录

InnoDB 在 MySQL 5.5 后成为默认索引,它的特点是:

  • 支持行锁,采用 MVCC 来支持高并发
  • 支持事务
  • 支持外键
  • 支持崩溃后的安全恢复

二者比较:
MyISAM 适合 SELECT 密集型的表,而 InnoDB 适合 INSERT 和 UPDATE 密集型的表

硬件升级:

1.配置多核心和频率高的cpu,多核心可执行多个线程
2.配置大内存可提高缓存容量,减少磁盘I/O,提高响应速度。
3.优化数据库参数,通过my.cnf和my.ini,修改性能影响较大的几个参数:
key_buffer_size:索引缓冲区大小
table_cache:能同时打开表的个数
query_cache_size和query_cache_type:查询缓冲区大小和前面参数的开关;0表示不使用缓冲区,1表示使用。查询使用SQL_NO_CACHE表示不使用缓冲区,查询使用SQL_CACHE表示使用缓冲区。
根据 MySQL 是 CPU 密集型还是 I/O 密集型,通过提升 CPU 和内存、使用 SSD,都能显著提升 MySQL 性能。
4.分库分表,读写分离

1)水平分库

以字段为依据,按照一定策略(hash、range等),将一个库中的数据拆分到多个库中。
结果:

  • 每个库的结构都一样;
  • 每个库的数据都不一样,没有交集;
  • 所有库的并集是全量数据;

应用场景:系统绝对并发量上来了,分表难以根本上解决问题,并且还没有明显的业务归属来垂直分库。
分析:库多了,io和cpu的压力自然可以成倍缓解。

2)水平分表

以字段为依据,按照一定策略(hash、range等),将一个表中的数据拆分到多个表中。
结果:

  • 每个表的结构都一样;
  • 每个表的数据都不一样,没有交集;
  • 所有表的并集是全量数据;

应用场景:系统绝对并发量并没有上来,只是单表的数据量太多,影响了SQL效率,加重了CPU负担,以至于成为瓶颈。
分析:表的数据量少了,单次SQL执行效率高,自然减轻了CPU的负担。

3)垂直分库

以表为依据,按照业务归属不同,将不同的表拆分到不同的库中。
结果:

  • 每个库的结构都不一样;
  • 每个库的数据也不一样,没有交集;
  • 所有库的并集是全量数据;

应用场景:系统绝对并发量上来了,并且可以抽象出单独的业务模块。
分析:到这一步,基本上就可以服务化了。例如,随着业务的发展一些公用的配置表、字典表等越来越多,这时可以将这些表拆到单独的库中,甚至可以服务化。再有,随着业务的发展孵化出了一套业务模式,这时可以将相关的表拆到单独的库中,甚至可以服务化。

4)垂直分表

以字段为依据,按照字段的活跃性,将表中字段拆到不同的表(主表和扩展表)中。
结果:

  • 每个表的结构都不一样;
  • 每个表的数据也不一样,一般来说,每个表的字段至少有一列交集,一般是主键,用于关联数据;
  • 所有表的并集是全量数据;

应用场景:系统绝对并发量并没有上来,表的记录并不多,但是字段多,并且热点数据和非热点数据在一起,单行数据所需的存储空间较大。以至于数据库缓存的数据行减少,查询时会去读磁盘数据产生大量的随机读IO,产生IO瓶颈。
分析:可以用列表页和详情页来帮助理解。垂直分表的拆分原则是将热点数据(可能会冗余经常一起查询的数据)放在一起作为主表,非热点数据放在一起作为扩展表。这样更多的热点数据就能被缓存下来,进而减少了随机读IO。拆了之后,要想获得全部数据就需要关联两个表来取数据。但记住,千万别用join,因为join不仅会增加CPU负担并且会讲两个表耦合在一起(必须在一个数据库实例上)。关联数据,应该在业务Service层做文章,分别获取主表和扩展表数据然后用关联字段关联得到全部数据。
分库分表工具:

  1. sharding-sphere:jar,前身是sharding-jdbc;客户端模式 jar
  2. TDDL:jar,Taobao Distribute Data Layer; TDDL为代表的应用层
  3. Mycat:proxy中间件层

你可能感兴趣的:(mysql)