Mysql引擎概述+索引+sql优化

时间:2021-10-24 23:46:35

本文说的Mysql是5.6版本。Mysql的存储引擎主要有: 1. MyIsam , 2. InnoDB, 3. Memory, 4. Blackhole, 5. CSV, 6. Performance_Schema, 7. Archive, 8. Federated , 9 Mrg_Myisam。

一.查看引擎

用show engines可以查看自己数据库支持哪些存储引擎:

Mysql引擎概述+索引+sql优化

 

二.修改引擎

   1.在文件my.ini里面,在[mysqld]后面添加default-storage-engine=InnoDB,重启服务。

   2.建表时指定

create table test(   
    id int primary key,   
    name varchar(50)   
)type=MyISAM;

   3. alter table table_name type = InnoDB;

三 引擎介绍

   1. InnoDB

InnoDB是一个事务型的存储引擎,有行级锁定和外键约束。但是该引擎不支持FULLTEXT类型的索引,而且它没有保存表的行数,当SELECT COUNT(*) FROM TABLE时需要扫描全表。当需要使用数据库事务时,该引擎当然是首选。由于锁的粒度更小,写操作不会锁定全表,所以在并发较高时,使用Innodb引擎会提升效率。但是使用行级锁也不是绝对的,如果在执行一个SQL语句时MySQL不能确定要扫描的范围,InnoDB表同样会锁全表。

适用场景:

1)经常更新的表,适合处理多重并发的更新请求。

2)支持事务。

3)可以从灾难中恢复(通过bin-log日志等)。

4)外键约束。只有他支持外键。

5)支持自动增加列属性auto_increment。

这里顺便提一下事务的特点(ACID):

A 事务的原子性(Atomicity):指一个事务要么全部执行,要么不执行.也就是说一个事务不可能只执行了一半就停止了.比如你从取款机取钱,这个事务可以分成两个步骤:1划卡,2出钱.不可能划了卡,而钱却没出来.这两步必须同时完成.要么就不完成.

C 事务的一致性(Consistency):指事务的运行并不改变数据库中数据的一致性.例如,完整性约束了a+b=10,一个事务改变了a,那么b也应该随之改变.

I 独立性(Isolation):事务的独立性也有称作隔离性,是指两个以上的事务不会出现交错执行的状态.因为这样可能会导致数据不一致.

D 持久性(Durability):事务的持久性是指事务执行成功以后,该事务所对数据库所作的更改便是持久的保存在数据库之中,不会无缘无故的回滚.

2.MyIsam

MyIASM是MySQL默认的引擎,但是它没有提供对数据库事务的支持,也不支持行级锁和外键,因此当INSERT(插入)或UPDATE(更新)数据时即写操作需要锁定整个表,效率便会低一些。

MyIsam 存储引擎独立于操作系统,也就是可以在windows上使用,也可以比较简单的将数据转移到linux操作系统上去。

适用场景:

1)不支持事务的设计,但是并不代表着有事务操作的项目不能用MyIsam存储引擎,可以在service层进行根据自己的业务需求进行相应的控制。

2)不支持外键的表设计。

3)查询速度很快,如果数据库insert和update的操作比较少的话比较适用。

4)整天 对表进行加锁的场景。

5)MyISAM极度强调快速读取操作。

6)MyIASM中存储了表的行数,于是SELECT COUNT(*) FROM TABLE时只需要直接读取已经保存好的值而不需要进行全表扫描。如果表的读操作远远多于写操作且不需要数据库事务的支持,那么MyIASM也是很好的选择。

3.Memory

使用存在内存中的内容来创建表。每个MEMORY表只实际对应一个磁盘文件。MEMORY类型的表访问非常得快,因为它的数据是放在内存中的,并且默认使用HASH索引。

但是一旦服务关闭,表中的数据就会丢失掉。

适用场景:

1)那些内容变化不频繁的代码表,或者作为统计操作的中间结果表,便于高效地堆中间结果进行分析并得到最终的统计结果。

2)目标数据比较小,而且非常频繁的进行访问,在内存中存放数据,如果太大的数据会造成内存溢出。可以通过参数max_heap_table_size控制Memory表的大小,限制Memory表的最大的大小。

3)数据是临时的,而且必须立即可用得到,那么就可以放在内存中。

4)存储在Memory表中的数据如果突然间丢失的话也没有太大的关系。

4.Mrg_Myisam

将MyIsam引擎的多个表聚合起来,但是他的内部没有数据,真正的数据依然是MyIsam引擎的表中,但是可以直接进行查询、删除更新等操作。

四 引擎比较

1)事务。MyISAM类型不支持事务处理等高级处理,而InnoDB类型支持,提供事务支持已经外部键等高级数据库功能。InnoDB表的行锁也不是绝对的,假如在执行一个SQL语句时MySQL不能确定要扫描的范围,InnoDB表同样会锁全表,例如updatetable set num=1 where name like “a%”,就是说在不确定的范围时,InnoDB还是会锁表的。

2)性能主题。MyISAM类型的表强调的是性能,其执行数度比InnoDB类型更快。

3)行数保存。InnoDB 中不保存表的具体行数,也就是说,执行select count() fromtable时,InnoDB要扫描一遍整个表来计算有多少行,但是MyISAM只要简单的读出保存好的行数即可。注意的是,当count()语句包含where条件时,两种表的操作是一样的。

4)索引存储。对于AUTO_INCREMENT类型的字段,InnoDB中必须包含只有该字段的索引,但是在MyISAM表中,可以和其他字段一起建立联合索引。

MyISAM支持全文索引(FULLTEXT)、压缩索引,InnoDB不支持

MyISAM的索引和数据是分开的,并且索引是有压缩的,内存使用率就对应提高了不少。能加载更多索引,而Innodb是索引和数据是紧密捆绑的,没有使用压缩从而会造成Innodb比MyISAM体积庞大不小。

InnoDB存储引擎被完全与MySQL服务器整合,InnoDB存储引擎为在主内存中缓存数据和索引而维持它自己的缓冲池。InnoDB存储它的表&索引在一个表空间中,表空间可以包含数个文件(或原始磁盘分区)。这与MyISAM表不同,比如在MyISAM表中每个表被存在分离的文件中。InnoDB 表可以是任何尺寸,即使在文件尺寸被限制为2GB的操作系统上。

5)服务器数据备份。InnoDB必须导出SQL来备份,LOAD TABLE FROM MASTER操作对InnoDB是不起作用的,解决方法是首先把InnoDB表改成MyISAM表,导入数据后再改成InnoDB表,但是对于使用的额外的InnoDB特性(例如外键)的表不适用。

而且MyISAM应对错误编码导致的数据恢复速度快。MyISAM的数据是以文件的形式存储,所以在跨平台的数据转移中会很方便。在备份和恢复时可单独针对某个表进行操作。

InnoDB是拷贝数据文件、备份 binlog,或者用 mysqldump,在数据量达到几十G的时候就相对痛苦了。

**6)锁的支持。**MyISAM只支持表锁。InnoDB支持表锁、行锁 行锁大幅度提高了多用户并发操作的新能。但是InnoDB的行锁,只是在WHERE的主键是有效的,非主键的WHERE都会锁全表的。

以下两点必须使用 InnoDB:

1)可靠性高或者要求事务处理,则使用InnoDB。这个是必须的。

2)表更新和查询都相当的频繁,并且表锁定的机会比较大的情况指定InnoDB数据引擎的创建。

对比之下,MyISAM的使用场景:

1)做很多count的计算的。如一些日志,调查的业务表。

2)插入修改不频繁,查询非常频繁的。

五 索引

目前索引方式有HASH和BTREE索引,MyISAM存储引擎支持FULLTEXT索引。

1. 索引分类

 普通索引:MySQL中基本索引类型,没有什么限制,允许在定义索引的列中插入重复值和空值。

 唯一索引:索引列中的值必须是唯一的,但是允许为空值。

    主键索引:是一种特殊的唯一索引,不允许有空值。

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

    全文索引:全文索引,只有在MyISAM引擎上才能使用,只能在CHAR,VARCHAR,TEXT类型字段上使用全文索引。

    空间索引:空间索引是对空间数据类型的字段建立的索引,MySQL中的空间数据类型有四种,GEOMETRY、POINT、LINESTRING、POLYGON。在创建空间索引时,使用SPATIAL关键字。要求,引擎为MyISAM,创建空间索引的列,必须将其声明为NOT NULL。

2. 索引操作

    创建索引:创建索引有几种方式,可以在创建表时创建,如:

CREATE TABLE 表名[字段名 数据类型]  [UNIQUE|FULLTEXT|SPATIAL|...] [INDEX|KEY] [索引名字] (字段名[length]) 

  CREATE TABLE t1

                (

                  id INT NOT NULL,

                  name CHAR(30) NOT NULL,

                  UNIQUE INDEX UniqIdx(id)

                ); 

    也可以在创建表后创建索引,

ALTER TABLE 表名 ADD[UNIQUE|FULLTEXT|SPATIAL] [INDEX|KEY] [索引名] (索引字段名)[ASC|DESC]

ALTER TABLE test ADD INDEX test_index(name(30));

CREATE INDEX test_index ON test(name);

    删除索引:ALTER TABLE 表名 DROP INDEX 索引名。

                      DROP INDEX 索引名 ON 表名;

    查看索引:用explain加载sql语句前面

EXPLAIN SELECT * FROM t WHERE id = 1

Mysql引擎概述+索引+sql优化

图中,possible_keys:MySQL在搜索数据记录时可以选用的各个索引,key:实际用的索引。

3.索引优化

1)NULL值的列:只要列中包含有NULL值都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此复合索引就是无效的。所以我们在数据库设计时不要让字段的默认值为NULL。

2)索引列排序:MySQL查询只使用一个索引,因此如果where子句中已经使用了索引的话,那么order by中的列是不会使用索引的。因此数据库默认排序可以符合要求的情况下不要使用排序操作;尽量不要包含多个列的排序,如果需要最好给这些列创建复合索引。

3)like语句:like “%aaa%” 不会使用索引,而like “aaa%”可以使用索引,建议没有必要的话尽量不要使用like。

4)避免在列上使用函数或运算:

5)组合索引顺序:对多列进行索引(组合索引),列的顺序非常重要,MySQL仅能对索引最左边的前缀进行有效的查找。例如:
假设存在组合索引indexc1c2(c1,c2),查询语句select * from t1 where c1=1 and c2=2能够使用该索引。查询语句select * from t1 where c1=1也能够使用该索引。但是,查询语句select * from t1 where c2=2不能够使用该索引。

6)  值重复少的字段不适合建索引,例:性别。

7)用or分割的条件,如果or前的条件中的列有索引,而后面的列没有索引,那么涉及的索引都不会用到。

<,<=,=,>,>=,between,in,以及不以通配符%或_开头的like才会使用索引。索引也不是越多越好,索引会占用空间和内存,多了维护成本也很高,更新数据时也会慢。

4.其他sql方面的优化

避免使用select *。

用count(1) 或count(列)代替count(*)

避免用or,可以用in或union代替。

用join代替子查询。

用exists代替in。

尽量不用not in,<>,避免扫描全表。

使用批量插入。

避免数据类型不一致。

 

可以加入慢查询日志分析,explain分析索引,profile跟踪sql。