mysql优化 | 存储引擎,建表,索引,sql的优化建议

我的对于选择存储引擎,建表,建索引,sql优化的一些总结,给读者提供一些参考意见mysql

推荐访问个人我的网站,排版更好看: chenmingyu.top/mysql-optim…sql

存储引擎

mysql中查看支持的引擎的sql:缓存

show engines; 
复制代码

在这里插入图片描述

平常工做中使用较多的存储引擎对比:InnoDB,MyISAM安全

InnoDB MyISAM
存储限制 64T 256T
支持事务 yes no
支持索引 yes yes
支持全文索引 no yes
支持数据缓存 yes no
支持外键 yes no
支持Hash索引 no no

从MySQL5.6版本开始InnoDB已经支持建立全文索引了性能优化

innodb

支持提交、回滚和崩溃恢复能力的事物安全(ACID),支持行锁,支持外键完整性约束bash

适合场景并发

  • 须要事务处理
  • 表数据量大,高并发操做
MyISAM

MyISAM存储引擎提供了高速检索和存储的能力,支持全文索引高并发

适合场景性能

  • 不少count计算的
  • 查询很是频繁的

其他几种存储引擎优化

MEMORY引擎

数据只保存在内存中,由于是在内存中,拥有极高的插入,更新,查询的效率,可是重启后数据都会丢失,表级锁,并发性能低。

MERGE引擎

merge表是一组MyISAM表的组合,因此merge表是没有数据的,对这个表的操做其实是操做内部的MyISAM表,将多个MyISAM表合并适合作一些报表之类的操做。

ARCHIVE引擎

仅支持插入和查询,使用zlib压缩库,在记录被请求的时候实时压缩,不支持事务,支持行级锁,适合存储大量的日志数据。

我的是推荐Innodb引擎的,公司部门里也是规定新建表的时候必须使用Innodb引擎,Innodb引擎较MyISAM引擎能够提供更多的功能,不是很实时的查询场景可使用缓存,近实时的查询可使用es,固然了这只是我的见解,针对不一样的场景选择不一样的存储引擎仍是颇有必要滴。因此在知道不一样存储引擎的特性以后,才能够根据不一样业务需求选择合适的存储引擎。

建表原则

在建表的时候尽可能遵循如下原则
  1. 尽可能选择小的数据类型,数据类型选择上尽可能tinyint(1字节)>smallint(2字节)>int(4字节)>bigint(8字节),好比逻辑删除yn字段上(1表明可用,0表明)就能够选择tinyint(1字节)类型

  2. 尽可能保证字段数据类型长度固定

  3. 尽可能避免使用null,使用null的字段查询很难优化,影响索引,可使用0或''代替

  4. 避免宽表,能拆分就拆分,一个表每每跟一个实体域对应,就像设计对象的时候同样,保持单一原则

  5. 尽可能避免使用text和blob,若是非使用不可,将类型为text和blob的字段在独立成一张新表,而后使用主键对应原表

  6. 禁止使用float或double类型,这个坑超大,float或double存在精度问题,在进行比较或者加减操做的时候会丢失精度致使数据异常,凡是使用float或double类型的时候考虑下可不可以使用int或bigint代替。好比金额,以元为单位使用float或double类型的时候,能够考虑以分为单位使用int,bigint类型代替,而后由业务代码进行单位的转换。

  7. 每张表都加上createUser,createTime.updateUser,updateTime字段

  8. 起名字要规范,包括:库名,表名,字段名,索引名

  9. 查询频繁使用的字段记得加索引

  10. 尽可能避免使用外键,不用外键约束,性能更高,而后数据的完整性有程序进行管理

  11. 若是表的数量能够预测到很是大,最好在建表的时候,就进行分表,不至于一时间数据量很是大致使效率问题

    未完待补充,,,

索引

索引是为来加速对表中数据行中的检索而建立的一种分散的数据结果,是针对表而创建的,它是由数据页面之外的索引页面组成,每一个索引页中的行都含有逻辑指针,以便加速检索物理数据,建立索引的目的在于提升查询效率,innodb的索引都是基于b tree实现的

索引类型

普通索引:最基本的索引,无限制

#方式1
CREATE INDEX idx_username ON sys_user(user_name(32)); 
#方式2
ALTER table sys_user ADD INDEX idx_username(user_name(32))
复制代码

主键索引:一个表只能有一个主键索引,且不能为空

通常建表时同时建立了主键索引

CREATE TABLE `sys_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_name` varchar(32) DEFAULT NULL,
  `pass_word` varchar(32) DEFAULT NULL,
  `token` varchar(32) DEFAULT NULL,
  `token_expire` int(11) DEFAULT NULL,
  `yn` smallint(6) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=348007 DEFAULT CHARSET=utf8;
复制代码

惟一索引:与普通索引相似,不一样的就是:索引列的值必须惟一,但容许有空值。若是是组合索引,则列值的组合必须惟一

CREATE UNIQUE INDEX idx_token ON sys_user(token_expire)
复制代码

组合索引:指多个字段上建立的索引,只有在查询条件中使用了建立索引时的第一个字段,索引才会被使用。使用组合索引时遵循最左前缀集合

ALTER TABLE sys_user ADD INDEX idx_un_te (user_name(32),token_expire); 
复制代码

全文索引:用来查找文本中的关键字,而不是直接与索引中的值相比较。只有char、varchar,text 列上能够建立全文索引

CREATE FULLTEXT INDEX idx_ ON sys_user(pass_word)
复制代码
建立使用索引的原则
  1. 索引的字段尽可能要小,根据索引查询数据的快慢取决于b tree的高度,当数据量恒定的时候,字节越少,存的索引的数量就越多,树的高度就越会越低

    好比:设置varchar(10),则这个索引创建的时候只会存字段前10个字节,字段设置的字节数比较小可能会致使索引查出来的数据多,进而进行回表,致使性能降低,因此字段设置为多少仍是要本身斟酌一下

  2. 遵循索引的最左匹配原则

  3. 注意使用like的时候尽可能不要使用“%a%”,这样的不走索引,可使用“a%”,走索引

  4. 不要在索引的列上进行计算,好比 select * from sys_user where token_expire+1 = 10000,这样的语句 不会走有索引

  5. 什么样的字段建索引,就是那种频繁在where,group by,order by中出现的列,最好加上索引

  6. 使用联合索引的时候尽可能考虑到索引下推优化

  7. 对于使用or的条件,须要or左右的条件都是索引才会走索引,不然走全表扫描,能够考虑使用union代替

  8. 避免使用select *,对于只须要查询主键或者where 条件中只有索引的字段, 这时会走覆盖索引建少回表次数

  9. sql语句中避免隐式转换,在MySQL中,字符串和数字作比较的话,是将字符串转换成数字,如字段是varchar类型,可是入参是int类型,即使字段有索引也不会走,由于这里会进行一次隐式转换

总之使用索引的时候,须要考虑的地方比较多,可是归根结底就是查询尽可能走索引,走索引尽可能避免回表或减小回表次数

索引的缺点

虽然索引的能够提升查询的效率,可是在进行insert,update,和delete的时候会下降效率,由于在保存数据的同时也会去保存索引。

不要在一个表里建过多的索引,问题跟上面同样,在操做数据的时候效率下降,并且数据量少的表要看状况建索引,若是建索引跟没建索引的效果差很少少的状况下就不要建索引了,若是是数据量大的表,就须要建索引去优化查询效率。

explain分析sql

可使用explain去分析sql的执行状况,好比

explain select * from sys_user where token_expire = 10000; 
复制代码

在这里插入图片描述

在阿里的开发手册中提到过,sql性能优化的标准:至少要达到range,要求ref级别,若是能够是consts最好

说明一下,这里的级别指的就是上图的type字段:

  • consts 是指单表中最多只有一个匹配行(主键或惟一索引)
  • ref 指的是使用普通索引
  • range 是指对索引进行范围查询

sql优化

关于sql语句的优化主要是两方面,一个是在建sql的时候须要注意的问题,另外一个就是在发现有慢sql的时候能够根据不一样状况进行分析,而后优化sql

优化的建议
  1. 查询的时候必定要记得使用limit进行限制
  2. 对于结果只须要一条数据的查询用limit 1进行限制
  3. 使用count(*)或count(1)来统计行数来查询,使用count(列)的时候,须要在查看列中这个是否为null,不会统计此列为null的状况,并且mysql已经对count(*)作了优化
  4. 不要使用select * 来查数据,使用select 须要的列名,这样的方式去查询
  5. 使用join连接代替子查询
  6. 不要使用外键,外键的约束能够放在程序里解决
  7. 控制一下in操做的集合数量,不要太大了
  8. 针对慢查询使用explain去分析缘由,而后优化sql,让其尽可能走索引

上面说的四个方面就是我目前对于sql优化各个方面的注意事项,但愿能够给你们提供一个参考,有问题的能够指出来,交流交流

相关文章
相关标签/搜索