MySQL索引
一、什么是索引,为什么要使用索引?
索引用于快速找出在某个列中有一特定值的行,不使用索引,MySQL必须从第一条记录开始读完整个表,直到找出相关的行,表越大,查询数据所花费的时间就越多,如果表中查询的列有一个索引,MySQL能够快速到达一个位置去搜索数据文件,而不必查看所有数据,那么将会节省很大一部分时间。
二、MySQL中索引的优点和缺点还有使用原则
优点:
- 所有的MySql列类型(字段类型)都可以被索引,也就是可以给任意字段设置索引
- 大大加快数据的查询速度
缺点:
- 创建索引和维护索引要耗费时间,并且随着数据量的增加所耗费的时间也会增加
- 索引也需要占空间,我们知道数据表中的数据也会有最大上线设置的,如果我们有大量的索引,索引文件可能会比数据文件更快达到上线值
- 当对表中的数据进行增加、删除、修改时,索引也需要动态的维护,降低了数据的维护速度。
使用原则:
1. 对经常更新的表就避免对其进行过多的索引,对经常用于查询的字段应该创建索引
2. 数据量小的表最好不要使用索引,因为由于数据较少,可能查询全部数据花费的时间比遍历索引的时间还要短,索引就可能不会产生优化效果。
3. 在一同值少的列上(字段上)不要建立索引,比如在学生表的"性别"字段上只有男,女两个不同值。相反的,在一个字段上不同值较多可以建立索引。
三、MySQL存储引擎
MyISAM存储引擎
不支持事务、也不支持外键,优势是访问速度快,对事务完整性没有 要求以select,insert为主的应用基本上可以用这个引擎来创建表
支持3种不同的存储格式,分别是:静态表;动态表;压缩表
静态表:表中的字段都是非变长字段,这样每个记录都是固定长度的,优点存储非常迅速,容易缓存,出现故障容易恢复;缺点是占用的空间通常比动态表多(因为存储时会按照列的宽度定义补足空格)ps:在取数据的时候,默认会把字段后面的空格去掉,如果不注意会把数据本身带的空格也会忽略。
动态表:记录不是固定长度的,这样存储的优点是占用的空间相对较少;缺点:频繁的更新、删除数据容易产生碎片,需要定期执行OPTIMIZE TABLE或者myisamchk-r命令来改善性能
压缩表:因为每个记录是被单独压缩的,所以只有非常小的访问开支
InnoDB存储引擎
该存储引擎提供了具有提交、回滚和崩溃恢复能力的事务安全。但是对比MyISAM引擎,写的处理效率会差一些,并且会占用更多的磁盘空间以保留数据和索引。
InnoDB存储引擎的特点:支持自动增长列,支持外键约束
MEMORY存储引擎
Memory存储引擎使用存在于内存中的内容来创建表。每个memory表只实际对应一个磁盘文件,格式是.frm。memory类型的表访问非常的快,因为它的数据是放在内存中的,并且默认使用HASH索引,但是一旦服务关闭,表中的数据就会丢失掉。
MEMORY存储引擎的表可以选择使用BTREE索引或者HASH索引,两种不同类型的索引有其不同的使用范围
Hash索引优点:
Hash 索引结构的特殊性,其检索效率非常高,索引的检索可以一次定位,不像B-Tree 索引需要从根节点到枝节点,最后才能访问到页节点这样多次的IO访问,所以 Hash 索引的查询效率要远高于 B-Tree 索引。
Hash索引缺点: 那么不精确查找呢,也很明显,因为hash算法是基于等值计算的,所以对于“like”等范围查找hash索引无效,不支持;
Memory类型的存储引擎主要用于哪些内容变化不频繁的代码表,或者作为统计操作的中间结果表,便于高效地对中间结果进行分析并得到最终的统计结果,。对存储引擎为memory的表进行更新操作要谨慎,因为数据并没有实际写入到磁盘中,所以一定要对下次重新启动服务后如何获得这些修改后的数据有所考虑。
四、索引的结构
mysql索引的数据结构是树,常用的存储引擎innodb采用的是B+Tree。这里对B+Tree及其相关的
查找树进行简要介绍:
1、二叉排序树(也称为二叉查找树)
二叉排序树是最简单的查找树,特点:
a)是一棵二叉树;
b)左子树所有结点的值小于它的父结点的值,右子树所有结点的值大于它的父结点的值。
2、平衡二叉树(又称AVL树)
平衡二叉树是二叉排序树的基础上,对树的深度进行了限制,从而减少了查找比较的次数,
特点:
a)是一棵二叉树;
b)左子树所有结点的值小于它的父结点的值,右子树所有结点的值大于它的父结点的值;
c)左子树与右子树的深度差在-1、0、1内,否则对子树进行旋转调整。
3、B-树(B-Tree)
B-树是多路平衡查找树,相对于平衡二叉树,对父结点的直接子结点个数,不再仅限于2,
可以指定m(自定义),这样可以在树的深度不大量增加的前提下,保存更多的结点。
B-树是通常在文件系统中使用。
特点:
a)树的每个结点最多有m(自定义)子结点;
b)若根结点不是叶子结点,则至少有两个子结点;
c) 除根结点外的所有非叶子结点,至少有m/2上取整个子结点;
d)父结点下的最左边子树所有结点的值均小于父结点最小值,
最右边子树所有结点的值均大于父结点最大值,
其余中间子树所有结点的值则介于指针的父结点两边的值;
e)所有叶子结点都在同一层;
注意:所有结点均带有值
4、B+树(B+Tree)
B+树是B-树变体,相对于B-树,叶子结点的值包含了所有的值,所有父结点的值是重复了叶子结点的值,
父结点只起索引查找的作用,同时所叶子结点也也构成了一条有序的链表。
mysql中存储引擎为innodb的索引,采用的数据结构即是B+树。
特点:
a)有m个子结点的父结点就有m个关键字;
b)所有叶子结点包含了所有关键字(值),且构成由小到大的有序链表;
c) 所有非叶子结点起索引作用,结点仅包含子树所有结点的最大值;
d)所有叶子结点都在同一层;
注意:叶子结点包含了所有的关键字(值)。
5、B树(BTree)
B*树是B+树的变体,相对B+树,增加了对同一层非叶子结点的指针,即同一层非叶子结点也构成了一条链表。
总结:
综上,上述各种查找树是相互关联的。
归结到mysql中innodb索引,采用的是B+树,如聚簇索引,是通过主键来聚集数据,采用B+树实现,
这即是一种索引,也是mysql的一种数据存储结构,叶子结点包含了所有的数据,非叶子结点仅起索引作用(若
没有定义主键,则innodb会隐式定义一个主键来作为聚簇索引)
索引的类型
注意:索引是在存储引擎中实现的,也就是说不同的存储引擎,会使用不同的索引
MyISAM和InnoDB存储引擎:只支持BTREE索引, 也就是说默认使用BTREE,不能够更换MEMORY/HEAP存储引擎:支持HASH和BTREE索引
索引我们分为四类来讲 单列索引(普通索引,唯一索引,主键索引)、组合索引、全文索引、空间索引、
- 单列索引:一个索引只包含单个列,但一个表中可以有多个单列索引。 这里不要搞混淆了。
(1)普通索引:MySQL中基本索引类型,没有什么限制,允许在定义索引的列中插入重复值和空值,纯粹为了查询数据更快一点。
(2)唯一索引:索引列中的值必须是唯一的,但是允许为空值,
(3)主键索引:是一种特殊的唯一索引,不允许有空值。
2. 组合索引
在表中的多个字段组合上创建的索引,只有在查询条件中使用了这些字段的左边字段时,索引才会被使用,使用组合索引时遵循最左前缀集合。
- 全文索引
全文索引,只有在MyISAM引擎上才能使用,只能在CHAR,VARCHAR,TEXT类型字段上使用全文索引,介绍了要求,说说什么是全文索引,就是在一堆文字中,通过其中的某个关键字等,就能找到该字段所属的记录行,比如有”你是个靓仔,靓女 …” 通过靓仔,可能就可以找到该条记录。这里说的是可能,因为全文索引的使用涉及了很多细节,我们只需要知道这个大概意思,如果感兴趣进一步深入使用它,那么看下面测试该索引时,会给出一个博文,供大家参考。
- 空间索引
空间索引是对空间数据类型的字段建立的索引,MySQL中的空间数据类型有四种,GEOMETRY、POINT、LINESTRING、POLYGON。在创建空间索引时,使用SPATIAL关键字。要求,引擎为MyISAM,创建空间索引的列,必须将其声明为NOT NULL。具体细节看下面
MySQL事务
原子性
一个事务中的所有操作,要么都完成,要么都不执行.对于一个事务来说,不可能只执行其中的一部分.
一致性
数据库总是从一个一致性的状态转换到另外一个一致性状态.
隔离性
一个事务所做的修改在最终提交以前,对其它事务是不可见的.多个事务之间的操作相互不影响. 每降低一个事务 隔离级别都能提高数据库的并发
1.读未提交 其它事务未提交就可以读
2.读已提交 其它事务只有提交了才能读
3.可重复读 只管自己启动事务时候的状态,不受其它事务的影响(mysql默认)
4.事务串行 按照顺序提交事务保证了数据的安全性,但无法实现并发
会出现的问题:
脏读:当一个事务读取到另外一个事务修改但未提交的数据时,就可能发生脏读。
不可重复读:“不可重复读”现象发生在当执行SELECT 操作时没有获得读锁或者SELECT操作执行完后马上释放了读锁; 另外一个事务对数据进行了更新,读到了不同的结果.(update)
幻读:“幻读”又叫”幻象读”,是’’不可重复读’’的一种特殊场景:当事务1两次执行’’SELECT … WHERE’’检索一定范围内数据的操作中间,事务2在这个表中创建了(如[[INSERT]])了一行新数据,这条新数据正好满足事务1的“WHERE”子句。(delete,insert.)
持久性
一旦一个事务已经提交了,就算服务器崩溃,仍然需要在下次启动的时候自动恢复.
结合事务日志完成:
事务日志写入磁盘的时候是顺序IO,写数据文件的时候是随机IO
一旦事务提交了,必须立即执行一个IO操作,确保此事务立即写入磁盘.