1.优化的方向
硬件: CPU、内存、存储、网络设备等
系统配置:服’务器系统、数据库服务参数等
数据库表结构:高可用、分库分表、读写分离、存储引擎、表设计等
Sql及索引: sql语句、索引使用等
- 从优化成本进行考虑:硬件>系统配置>数据库表结构>SQL及索引
- 从优化效果进行考虑:硬件<系统配置<数据库表结构<SQL及索引
检查问题常用工具
2.查询优化
主要实现办法是开启慢查询记录,分析sql语句或者使用EXPLAIN语句分析
3.索引优化
索引种类
主键索引 primary key() 唯一且不可重复
不可重复索引 unique key 可以重复多个列都可以标识唯一索引
常规索引 key /index
全文索引 fulltext
alter table xx add key 索引名(索引字段)
索引的存储结构
btree:
- BTREE索引以B+树的结构存储数据
- BTREE索引能够加快数据的查询速度
- BTREE索引更适合进行行范围查找
使用的场景:
- 全值匹配的查询,例如根据订单号查询 order_sn=‘98764322119900’
- 联合索引时会遵循最左前缀匹配的原则,即最左优先
- 匹配列前缀查询,例如:order_sn like '9876%
- 匹配范围值的查找,例如:order_sn > ‘98764322119900’
- 只访问索引的查询
哈希索引
Memory存储引擎中将Hash索引作为默认的索引类型。所谓Hash索引,实际上就是通过一定的Hash算法,将需要索引的键值进行Hash运算,然后将得到的Hash值存入一个Hash表中。然后每次需要检索的时候,都会将检索条件进行相同算法的Hash运算,然后再和Hash表中的Hash值进行比较并得出相应的信息
特点
Hash索引仅仅只能满足“=”,“IN”和“<=>”查询,不能使用范围查询;
Hash索引无法被利用来避免数据的排序操作;
Hash索引不能利用部分索引键查询;
Hash索引在任何时候都不能避免表扫描
Hash索引遇到大量Hash值相等的情况后性能并不一定就会比B-Tree索引高
Full-text全文索引
Full-text索引也就是我们常说的全文索引,MySQL中仅有MyISAM和InnoDB存储引擎支持。
对于文本的大对象,或者较大的CHAR类型的数据,如果使用普通索引,那么匹配文本前几个字符还是可行的,但是想要匹配文本中间的几个单词,那么就要使用LIKE %word%来匹配,这样需要很长的时间来处理,响应时间会大大增加,这种情况,就可使用时FULLTEXT索引了,在生成Full-text索引时,会为文本生成一份单词的清单,在索引时根据这个单词的清单来索引。
- 对于较大的数据集,把数据添加到一个没有Full-text索引的表,然后添加Full-text索引的速度比把数据添加到一个已经有Full-text索引的表快。
- 针对较大的数据,生成全文索引非常的消耗时间和空间。
- 5.6版本前的MySQL自带的全文索引只能用于MyISAM存储引擎,如果是其它数据引擎,那么全文索引不会生效。5.6版本和之后InnoDB存储引擎开始支持全文索引。在
- MySQL中,全文索引支队英文有用,目前对中文还不支持。5.7版本之后通过使用ngram插件开始支持中文。
- 在MySQL中,如果检索的字符串太短则无法检索得到预期的结果,检索的字符串长度至少为4字节。
总结
虽然索引能够为查找带来速度上的提升,但是也会对性能有一些损失。索引会增加写操作的成本太多的索引会增加查询优化器的选择时间当创建索引带来的好处多过于消耗的时候,才是最优的选择~
使用索引的场景
- 主键自动建立唯一索引;经常作为查询条件在WHERE或者ORDER BY 语句中出现的列要建立索引;
- 作为排序的列要建立索引;
- 查询中与其他表关联的字段,外键关系建立索引高并发条件下倾向建立组合索引;
- 用于聚合函数的列可以建立索引,例如使用count(number)时,number列就要建立索引
4.存储优化
InnoDB
- InnoDB存储引擎提供了具有提交、回滚和崩溃恢复能力的事务安全。相比较MyISAM存储引擎,InnoDB写的处理效率差一点并且会占用更多的磁盘空间保留数据和索引。
- 提供了对数据库事务ACID(原子性Atomicity、一致性Consistency、隔离性Isolation、持久性Durability)的支持,实现了SQL标准的四种隔离级别。
- 设计目标就是处理大容量的数据库系统,MySQL运行时InnoDB会在内存中建立缓冲池,用于缓冲数据和索引。
- 执行“select count(*) from table”语句时需要扫描全表,因为使用innodb引擎的表不会保存表的具体行数,所以需要扫描整个表才能计算多少行。
- InnoDB引擎是行锁,粒度更小,所以写操作不会锁定全表,在并发较高时,使用InnoDB会提升效率。即存在大量UPDATE/INSERT操作时,效率较高。
- InnoDB清空数据量大的表时,是非常缓慢,这是因为InnoDB必须处理表中的每一行,根据InnoDB的事务设计原则,首先需要把“删除动作”写入“事务日志”,然后写入实际的表。所以,清空大表的时候,最好直接drop table然后重建。即InnoDB一行一行删除,不会重建表。
使用场景
- 经常UPDETE/INSERT的表,使用处理多并发的写请求
- 可以从灾难中恢复(日志+事务回滚)
- 外键约束、列属性AUTO_INCREMENT支持
MyISAM存储引擎
- MyISAM不支持事务,不支持外键,SELECT/INSERT为主的应用可以使用该引擎。
- 每个MyISAM在存储成3个文件,扩展名分别是:1) frm:存储表定义(表结构等信息)2) MYD(MYData),存储数据3) MYI(MYIndex),存储索引
- 不同MyISAM表的索引文件和数据文件可以放置到不同的路径下。
- MyISAM类型的表提供修复的工具,可以用CHECK TABLE语句来检查MyISAM表健康,并用REPAIR TABLE语句修复一个损坏的MyISAM表。
- 在MySQL5.6以前,只有MyISAM支持Full-text全文索引
使用场景:
1.经常SELECT/INSERT的表,插入不频繁,查询非常频繁
2. 不支持事务
3. 做很多count 的计算。
MyISAM和Innodb区别
InnoDB和MyISAM是许多人在使用MySQL时最常用的两个存储引擎,这两个存储引擎各有优劣,视具体应用而定。基本的差别为:MyISAM类型不支持事务处理,而InnoDB类型支持。MyISAM类型强调的是性能,其执行速度比InnoDB类型更快,而InnoDB提供事务支持已经外部键等高级数据库功能
- MyISAM是非事务安全型的,而InnoDB是事务安全型的。
- MyISAM锁的粒度是表级,而InnoDB支持行级锁定。
- MyISAM不支持外键,而InnoDB支持外键
- MyISAM相对简单,所以在效率上要优于InnoDB,小型应用可以考虑使用MyISAM。
- InnoDB表比MyISAM表更安全
5. 数据库结构优化
优化表结构
- 尽量将表字段定义为NOT NULL约束,这时由于在MySQL中含有空值的列很难进行查询优化,NULL值会使索引以及索引的统计信息变得很复杂。
- 对于只包含特定类型的字段,可以使用enum、set 等数据类型。
- 数值型字段的比较比字符串的比较效率高得多,字段类型尽量使用最小、最简单的数据类型。例如IP地址可以使用int类型。
- 尽量使用TINYINT、SMALLINT、MEDIUM_INT作为整数类型而非INT,如果非负则加上UNSIGNED。但对整数类型指定宽度,比如INT(11),没有任何用,因为指定的类型标识范围已经确定。
- VARCHAR的长度只分配真正需要的空间
- 单表不要有太多字段,建议在20以内
- 合理的加入冗余字段可以提高查询速度。
表拆分
垂直拆分
垂直拆分按照字段进行拆分,其实就是把组成一行的多个列分开放到不同的表中,这些表具有不同的结构,拆分后的表具有更少的列。例如用户表中的一些字段可能经常访问,可以把这些字段放进一张表里。另外一些不经常使用的信息就可以放进另外一张表里
插入的时候使用事务,也可以保证两表的数据一致。缺点也很明显,由于拆分出来的两张表存在一对一的关系,需要使用冗余字段,而且需要join操作。但是我们可以在使用的时候可以分别取两次,这样的来说既可以避免join操作,又可以提高效率
水平拆分
水平拆分按照行进行拆分,常见的就是分库分表。以用户表为例,可以取用户ID,然后对ID取10的余数,将用户均匀的分配进这 0-9这10个表中。查找的时候也按照这种规则,又快又方便。
有些表业务关联比较强,那么可以使用按时间划分的。例如每天的数据量很大,需要每天新建一张表。这种业务类型就是需要高速插入,但是对于查询的效率不太关心。表越大,插入数据所需要索引维护的时间也就越长
表分区
分区适用于例如日志记录,查询少。一般用于后台的数据报表分析。对于这些数据汇总需求,需要很多日志表去做数据聚合,我们能够容忍1s到2s的延迟,只要数据准确能够满足需求就可以。MySQL主要支持4种模式的分区:range分区、list预定义列表分区,hash 分区,key键值分区。