一,什么是索引:
索引是对数据库表中一列或多列的值进行排序的一种结构。在关系数据库中,索引是一种与表有关的数据库结构,它可以使对应于表的SQL语句执行得更快。索引的作用相当于图书的目录,可以根据目录中的页码快速找到所需的内容。当表中有大量记录时,若要对表进行查询,第一种搜索信息方式是全表搜索,是将所有记录一一取出,和查询条件进行一一对比,然后返回满足条件的记录,这样做会消耗大量数据库系统时间,并造成大量磁盘I/O操作;第二种就是在表中建立索引,然后在索引中找到符合查询条件的索引值,最后通过保存在索引中的ROWID(相当于页码)快速找到表中对应的记录。
索引的定义概念
索引是一个单独的、物理的数据库结构,它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单。索引提供指向存储在表的指定列中的数据值的指针,然后根据您指定的排序顺序对这些指针排序。数据库使用索引的方式与您使用书籍中的索引的方式很相似:它搜索索引以找到特定值,然后顺指针找到包含该值的行。在数据库关系图中,可以在选定表的“索引/键”属性页中创建、编辑或删除每个索引类型。当保存索引所附加到的表,或保存该表所在的关系图时,索引将保存在数据库中。
二,MySql索引与所支持的索引:
MySql所有的列都可以添加索引,索引类似于书本中的页码,可以有效的提高select语句执行的效率
MySql支持的索引类型:
FULLTEXT(全文索引):
全文索引,目前只有MyISAM引擎支持。其可以在CREATE TABLE ,ALTER TABLE ,CREATE INDEX 使用,不过目前只有 CHAR、VARCHAR ,TEXT 列上可以创建全文索引。
支持:MyISAM,InnoDB
HASH:
其检索效率非常高,索引的检索可以一次定位,不像B-Tree 索引需要从根节点到枝节点,最后才能访问到页节点这样多次的IO访问,所以 Hash 索引的查询效率要远高于 B-Tree 索引
支持:只有Memory存储引擎显示支持hash索引
BTREE(B树索引):
BTREE索引就是一种将索引值按一定的算法,存入一个树形的数据结构中(二叉树),每次查询都是从树的入口root开始,依次遍历node,获取leaf。这是MySQL里默认和最常用的索引类型。
RTREE(R树索引):
RTREE在MySQL很少使用,仅支持geometry数据类型。相对于BTREE,RTREE的优势在于范围查找。
支持:MyISAM,InnoDb
这里支持的存储引擎只考虑了MySql中常用的4中引擎。关于四种常见引擎可见MySql四种常见存储引擎
三,关于B树与B+树:详情来自为什么MongoDB采用B树索引,而Mysql用B+树做索引
先从数据结构的角度来答。
题主应该知道B-树和B+树最重要的一个区别就是B+树只有叶节点存放数据,其余节点用来索引,而B-树是每个索引节点都会有Data域。
这就决定了B+树更适合用来存储外部数据,也就是所谓的磁盘数据。
从Mysql(Inoodb)的角度来看,B+树是用来充当索引的,一般来说索引非常大,尤其是关系性数据库这种数据量大的索引能达到亿级别,所以为了减少内存的占用,索引也会被存储在磁盘上。
那么Mysql如何衡量查询效率呢?磁盘IO次数,B-树(B类树)的特定就是每层节点数目非常多,层数很少,目的就是为了就少磁盘IO次数,当查询数据的时候,最好的情况就是很快找到目标索引,然后读取数据,使用B+树就能很好的完成这个目的,但是B-树的每个节点都有data域(指针),这无疑增大了节点大小,说白了增加了磁盘IO次数(磁盘IO一次读出的数据量大小是固定的,单个数据变大,每次读出的就少,IO次数增多,一次IO多耗时啊!),而B+树除了叶子节点其它节点并不存储数据,节点小,磁盘IO次数就少。这是优点之一。
另一个优点是什么,B+树所有的Data域在叶子节点,一般来说都会进行一个优化,就是将所有的叶子节点用指针串起来。这样遍历叶子节点就能获得全部数据,这样就能进行区间访问啦。
至于MongoDB为什么使用B-树而不是B+树,可以从它的设计角度来考虑,它并不是传统的关系性数据库,而是以Json格式作为存储的nosql,目的就是高性能,高可用,易扩展。首先它摆脱了关系模型,上面所述的优点2需求就没那么强烈了,其次Mysql由于使用B+树,数据都在叶节点上,每次查询都需要访问到叶节点,而MongoDB使用B-树,所有节点都有Data域,只要找到指定索引就可以进行访问,无疑单次查询平均快于Mysql(但侧面来看Mysql至少平均查询耗时差不多)。
总体来说,Mysql选用B+树和MongoDB选用B-树还是以自己的需求来选择的。
四,主键和唯一索引的区别:
主键一定是唯一性索引,唯一性索引并不一定就是主键,可以说主键是一种特殊的唯一索引,主键主要是用来区分数据,防止有多余的重复数据,是逻辑键,但是唯一索引是物理键,主键不实际存在,但是索引是存在于数据库中的,索引是用来提升数据库的操作速度的。
比较:
空值:主键不能为空,但是唯一索引的索引列可以为空值
唯一:主键在一个表中唯一,但是可以创建多个唯一索引
五,事务的隔离机制,mysql默认是哪一级:
Repeated Read
关于四种隔离机制:
事务隔离级别 | 脏读 | 不可重复读 | 幻读 |
读未提交(read-uncommitted) | 是 | 是 | 是 |
不可重复读(read-committed) | 否 | 是 | 是 |
可重复读(repeatable-read) | 否 | 否 | 是 |
串行化(serializable) | 否 | 否 | 否 |
六,mysql中的各种锁,乐观锁,悲观锁(排他锁,共享锁);行锁,表锁的实现
乐观锁:
乐观锁不是数据库自己实现的,乐观锁是指操作数据库时(更新操作),想法很乐观,认为这次的操作不会导致冲突,在操作数据时,并不进行任何其他的特殊处理(也就是不加锁),而在进行更新后,再去判断是否有冲突了
实现:给数据表加一个版本(version)字段,每操作一次,将那条记录的版本号加1。也就是先查询出那条记录,获取出version字段,如果要对那条记录进行操作(更新),则先判断此刻version的值是否与刚刚查询出来时的version的值相等,如果相等,则说明这段期间,没有其他程序对其进行操作,则可以执行更新,将version字段的值加1;如果更新时发现此刻的version值与刚刚获取出来的version的值不相等,则说明这段期间已经有其他程序对其进行操作了,则不进行更新操作
悲观锁:在操作数据时,认为此操作会出现数据冲突,所以在进行每次操作时都要通过获取锁才能进行对相同数据的操作,所以悲观锁需要耗费较多的时间。另外与乐观锁相对应的,悲观锁是由数据库自己实现了的,要用的时候,我们直接调用数据库的相关语句就可以了
实现:这点跟java中的synchronized很相似
悲观锁(排他锁,共享锁):
悲观锁涉及到的两个概念,共享锁指的就是对于多个不同的事务,对同一个资源共享同一个锁。相当于对于同一把门,它拥有多个钥匙一样。就像这样,你家有一个大门,大门的钥匙有好几把,你有一把,你家人有一把,你们都可能通过这把钥匙进入你们家,这个就是所谓的共享锁。
排它锁与共享锁相对应,就是指对于多个不同的事务,对同一个资源只能有一把锁。与共享锁类型,在需要执行的语句后面加上for update就可以了
行锁:
行锁,由字面意思理解,就是给某一行加上锁,也就是一条记录加上锁。
表锁:
表锁,和行锁相对应,给这个表加上锁。
详情来自MySql锁
七,Mysql查询优化:
1)缓存,在持久层或持久层之上做缓存
使用ehcache缓存,这个一般用于持久层的缓存,提供持久层、业务层的快速缓存,hibenate默认使用的二级缓存就是ehcache;
2)数据库表的大字段剥离
假如一个表的字段数有100多个,学会拆分字段,保证单条记录的数据量很小;
(保证每次IO操作数据量的读取更有效,在可定范围内读到的数据更多)
3)恰当地使用索引
必要时建立多级索引,分析MySQL的执行计划,通过表数据统计等方式协助数据库走正确的查询方式,该走索引就走索引,该走全表扫描就走全表扫描;
4)表的拆分
表分区和拆分,无论是业务逻辑上的拆分(如一个月一张报表、分库)还是无业务含义的分区(如根据ID取模分区);
5)字段冗余
减少跨库查询和大表连接操作;,数据通过单个或多个JOB生成出来,减少实时查询;
6)从磁盘上做文章
数据存放的在磁盘的内、外磁道上,数据获取的效率都是不一样的;
7)放弃关系数据库的某些特性
引入NoSQL数据库;