MySql进阶-优化篇
MySQL架构
客户端层:提交sql语句
cli;jdbc;navicat;sqlyog
MySqlServer层
1.连接器:用来控制用户的连接,比如:连接池
show processlist;//查看连接池
2.分析器:词法分析和语法分析,形成抽象语法树(AST)
3.调优器:
CBO:基于成本的优化
RBO:基于规则的优化
4.执行器
存储引擎层:不同的存放位置,不同的文件格式
InnoDB存储引擎:有事务,默认支持行锁(但是也支持表锁)InnoDB一般锁的是索引,如果一张表内没有索引,那么就默认表级锁
.idb->实际存储的数据
.frm->存储表结构和存储表的位置
MyISAM存储引擎:索引文件和数据文件分开存放:没有事务,默认支持表锁
.frm
.MYD->Data
.MYI->Index
日志文件
binLog:归属于服务层(默认不开启)
redoLog:归属于InnoDB存储引擎
undoLog:归属于InnoDB存储引擎
一般要开启binLog是为了防止数据丢失,开启后可以做数据恢复(会损失一点性能)
MySql的存储引擎
ISAM:(Indexed Sequential Access Method)索引序列访问方法,是一种数据表格的管理方法,设计之时就考虑到了查询远大于更新次数,因此他的查询速度很快并且不占用大量内存和储存资源,但是他有两个缺点:
- 不支持事务;
- 不能够容错:如果硬盘崩溃,则无法恢复数据,必须实时备份。
ISAM升级版(优化查询)
MyISAM:是MySql对ISAM的扩展和缺省的数据库引擎(在MySql5.5以后默认为InnoDB了),MyISAM还提供了一种表格锁定机制,优化多个并发的读写操作,但是它在做更新操作后可能会出现内存碎片,所以经常需要使用Optimize Table 表名,来整理碎片,在整理碎片的过程中该表是被锁定的状态,外界无法查询或更新,整理完成后才能正常使用,并且MyISAM也有个缺陷就是在表损坏后也不能恢复数据。
如果使用该引擎会生成三个文件:
- .frm:所有的表结构信息
- .MYD:表的数据记录
- .MYI:表的索引文件
数据库优化
数据库在优化的时候
- 能不优化就不优化
我们通过优化策略,会发现越往后受影响面积越广,越往前受面积越小:
- Sql语句
- 建索引:受影响的是一个列
- 修改引擎:受影响的是整个表
- 对数据库的内存分配做优化:影响整个数据库
索引
所以一般我们要优化数据库应该是首先考虑Sql语句优化以及索引优化,对于修改引擎是一件十分慎重的事情。
InnoDB
InnoDB:比ISAM和MyISAM的速度慢,但是包含了对事物和外来键的支持,MySql官方对InnoDB的解释:
- 提供了具有提交、回滚和崩溃恢复能力的事务安全(ACID兼容)存储引擎
- 锁定在行级,并且在Select语句提供一个Oracle风格的非锁定读
- 支持Foreign key强制(外键查询)
- CPU效率可能是任何关系型数据库不能匹敌的
MyISAM与InnoDB的区别
- InnoDB 支持事务,MyISAM 不支持。对于 InnoDB 每一条 SQL 语言都默认封装成事务; 自动提交,这样会影响速度,所以最好把多条 SQL 语言放在 begin transaction 和commit 之 间,组成一个事务;
- InnoDB 支持外键,而 MyISAM 不支持。对一个包含外键的 InnoDB 表转为 MYISAM 会失败;
- InnoDB 是聚集索引(对各个表的索引进行排列组合,以便于在查找的时候效率更高),数据文件是和索引绑在一起的,必须要有主键。(在使用该引擎的时候,即便没有设定默认主键,InnoDB也会自动根据你的表中的唯一性约束定位默认主键,如果连这个也没有,那么InnoDB会根据每个数据随机生成一个索引数),通过主键索引 效率很高。但是辅助索引(我们自己create index的索引)需要两次查询(即使是查询两次也不会影响效率,因为索引本身可以指定到唯一数据,即使是两次查询,速度也会非常快),先查询到主键,然后再通过主键查询到数据。因此,主键不应该过大,因为主键太大,其他索引也都会很大。而 MyISAM 是非聚集索引,数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的。
- InnoDB 不保存表的具体行数,执行 select count(*) from table 时需要全表扫描。而 MyISAM 用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快;
- Innodb 不支持全文索引,而 MyISAM 支持全文索引,查询效率上 MyISAM 较高;
整理一下
MyISAM | InnoDB | |
---|---|---|
索引类型 | 非聚簇索引 | 聚簇索引 |
支持事务 | 否 | 是 |
支持表锁 | 是 | 是 |
支持行锁 | 否 | 是 |
支持外键 | 否 | 是 |
支持全文索引 | 是 | 是(5.6后支持) |
适合操作类型 | 大量select | 大量insert,delete,update |
其他的引擎
- NDBCluster:5.0开始提供,用于分布式集群
- Merge:整合了一下ISAM分离的接口
- Memory:内存引擎
- BlackHole:无论写入什么信息,都是有去无回
- MySql同时也给我们提供了一个接口,让我们自己写数据库引擎。
操作数据库引擎
查看当前支持的所有存储引擎
mysql> show engines;
MyISAM
MEMORY
InnoDB
BerkeleyDB
BLACKHOLE
EXAMPLE
ARCHIVE
CSV
ndbcluster
FEDERATED
MRG_MYISAM
ISAM
12 rows in set (0.00 sec)
查看当前默认的存储引擎
mysql> SHOW VARIABLES LIKE '%storage_engine';
+----------------+--------+
| Variable_name | Value |
+----------------+--------+
| storage_engine | InnoDB |
+----------------+--------+
1 row in set (0.00 sec)
注意:不同的表可以使用不同的存储引擎
查看创建表时使用的引擎
mysql> show create table student;
CREATE TABLE `student` (
...
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
1 row in set (0.00 sec)
修改表的存储引擎
mysql> ALTER TABLE student ENGINE = InnoDB;
Query OK, 110 rows affected (0.03 sec)
Records: 110 Duplicates: 0 Warnings: 0
数据库的索引
为什么要建立索引?
这是因为,创建索引可以大大提高系统的查询性能: |
---|
1.通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。 |
2.可以大大加快数据的检索速度,这也是创建索引的最主要的原因。 |
3.可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。 |
4.在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。 |
在InnoDB创建表的过程中,首先确定表的主键,如果没有就找具有唯一性约束的数据做为主键,否则就自己为各个数据随机生成索引数,其目的就是为了提高查询效率,实际上索引最后会被换算成磁盘的存储位置,那么根据索引就能直接查询到数据。
- .idb:是InnoDB的数据文件
索引这么高效,为什么不对每个表的每个列都创建索引?
增加索引也有许多不利: |
---|
1.创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。 |
2.索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。 |
3.当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。 |
什么样的字段适合创建索引?
一般来说,应该在具备下述特性的列上创建索引: |
---|
1.在经常需要搜索的列上,可以加快搜索的速度 |
2.在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构 |
3.在经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度(在做互联网项目的时候,一般表之间有外键但是不建立外键约束,是为了分库分表) |
4.在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,其指定的范围是连续的 |
5.在经常需要排序的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间 |
6.在经常使用在 WHERE 子句中的列上面创建索引,加快条件的判断速度 |
什么样的字段不适合创建索引?
一般来说,不应该创建索引的这些列具有下述特点: |
---|
1.对于那些在查询中很少使用或者参考的列不应该创建索引。这是因为,既然这些列很少使用到,因此有索引或者无索引,并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。 |
2.对于那些只有很少数据值的列也不应该增加索引。这是因为,由于这些列的取值很少,例如人事表的性别列,在查询的结果中,结果集的数据行占了表中数据行的很大比例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加快检索速度。 |
3.对于那些定义为 text, image 和 bit 数据类型的列不应该增加索引。这是因为,这些列的数据量要么相当大,要么取值很少。 |
4.当修改性能远远大于检索性能时,不应该创建索引。这是因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因此,当修改性能远远大于检索性能时,不应该创建索引。 |