索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针.
索引是一种数据结构.数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中数据.索引的实现通常使用B树及其变种B+树.
更通俗的说,索引就相当于目录.为了方便查找书中的内容,通过对内容建立索引形成目录.索引是一个文件,它是要占据物理空间的.
索引的优点
可以大大加快数据的检索速度,这也是创建索引的最主要的原因.通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能.索引的缺点
时间方面:创建索引和维护索引要耗费时间,具体地,当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,会降低增/改/删的执行效率;空间方面:索引需要占物理空间.
主键索引: 数据列不允许重复,不允许为NULL,一个表只能有一个主键.
唯一索引: 数据列不允许重复,允许为NULL值,一个表允许多个列创建唯一索引.
可以通过 ALTER TABLE table_name ADD UNIQUE (column); 创建唯一索引
普通索引: 基本的索引类型,没有唯一性的限制,允许为NULL值.
可以通过ALTER TABLE table_name ADD INDEX index_name (column);创建普通索引
全文索引: 是目前搜索引擎使用的一种关键技术.
索引的数据结构和具体存储引擎的实现有关,在MySQL中使用较多的索引有Hash索引,B+树索引等,而我们经常使用的InnoDB存储引擎的默认索引实现为:B+树索引.对于哈希索引来说,底层的数据结构就是哈希表,所以呢在绝大多数需求为单条记录查询的时候,可以选择哈希索引,查询性能最快;其余大部分场景,建议选择BTree索引.
MySQL 跟 B+ 树没有直接的关系,真正与 B+ 树有关系的是 MySQL 的默认存储引擎 InnoDB,MySQL 中存储引擎的主要作用是负责数据的存储和提取,除了 InnoDB 之外,MySQL 中也支持 MyISAM 作为表的底层存储引擎.
B+tree性质:
①)n棵子tree的节点包含n个关键字,不用来保存数据而是保存数据的索引.
B+树是B树的改进,简单地说是:只有叶子节点才存数据,非叶子节点是存储的指针;所有叶子节点构成一个有序链表
B+树的内部节点并没有指向关键字具体信息的指针,所以呢其内部节点相对B树更小,如果把所有同一内部节点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多,一次性读入内存的需要查找的关键字也就越多,相对IO读写次数就降低了
B树只适合随机检索,而B+树同时支持随机检索和顺序检索;B+树空间利用率更高,可减少I/O次数,磁盘读写代价更低.一般来说,索引本身也很大,不可能全部存储在内存中,所以呢索引往往以索引文件的形式存储的磁盘上.这样的话,索引查找过程中就要产生磁盘I/O消耗.B+树的内部结点并没有指向关键字具体信息的指针,只是作为索引使用,其内部结点比B树小,盘块能容纳的结点中关键字数量更多,一次性读入内存中可以查找的关键字也就越多,相对的,IO读写次数也就降低了.而IO读写次数是影响索引检索效率的最大因素;B+树的查询效率更加稳定.B树搜索有可能会在非叶子结点结束,越靠近根节点的记录查找时间越短,只要找到关键字即可确定记录的存在,其性能等价于在关键字全集内做一次二分查找.而在B+树中,顺序检索比较明显,随机检索时,任何关键字的查找都必须走一条从根节点到叶节点的路,所有关键字的查找路径长度相同,导致每一个关键字的查询效率相当.B-树在提高了磁盘IO性能的同时并没有解决元素遍历的效率低下的问题.B+树的叶子节点使用指针顺序连接在一起,只要遍历叶子节点就可以实现整棵树的遍历.而且在数据库中基于范围的查询是非常频繁的,而B树不支持这样的操作.增删文件(节点)时,效率更高.因为B+树的叶子节点包含所有关键字,并以有序的链表结构存储,这样可很好提高增删效率.
Hash索引只能用于对等比较,例如=,(相当于=)操作符.由于是一次定位数据,不像BTree索引需要从根节点到枝节点,最后才能访问到页节点这样多次IO访问,所以检索效率远高于BTree索引.
事务是一个不可分割的数据库操作序列,也是数据库并发控制的基本单位,其执行的结果必须使数据库从一种一致性状态变到另一种一致性状态.事务是逻辑上的一组操作,要么都执行,要么都不执行.
原子性: 事务是最小的执行单位,不允许分割.事务的原子性确保动作要么全部完成,要么完全不起作用;
持久性: 一个事务被提交之后.它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响.
脏读(Drity Read):某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的.
不可重复读(Non-repeatable read):在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新的原有的数据.
幻读(Phantom Read):在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在此时此刻呢的查询中,就会发现有几列数据是它先前所没有的.
READ-UNCOMMITTED(读取未提交): 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读.(一个事务还没提交,就被别的事务看到了)
READ-COMMITTED(读取已提交): 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生.
REPEATABLE-READ(可重复读): 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生
SERIALIZABLE(可串行化): 最高的隔离级别,完全服从ACID的隔离级别.所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读.
当数据库有并发事务的时候,可能会产生数据的不一致,这时候需要一些机制来保证访问的次序,锁机制就是这样的一个机制.
就像酒店的房间,如果大家随意进出,就会出现多人抢夺同一个房间的情况,而在房间上装上锁,申请到钥匙的人才可以入住并且将房间锁起来,其他人只有等他使用完毕才可以再次使用.
MyISAM和InnoDB存储引擎使用的锁:
MyISAM采用表级锁(table-level locking).
InnoDB支持行级锁(row-level locking)和表级锁,默认为行级锁
行级锁是Mysql中锁定粒度最细的一种锁,表示只针对当前操作的行进行加锁.行级锁能大大减少数据库操作的冲突.其加锁粒度最小,但加锁的开销也最大.行级锁分为共享锁 和 排他锁.
特点:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高.
表级锁是MySQL中锁定粒度最大的一种锁,表示对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分MySQL引擎支持.最常使用的MYISAM与INNODB都支持表级锁定.表级锁定分为表共享读锁(共享锁)与表独占写锁(排他锁).
特点:开销小,加锁快;不会出现死锁;锁定粒度大,发出锁冲突的概率最高,并发度最低.
页级锁是MySQL中锁定粒度介于行级锁和表级锁中间的一种锁.表级锁速度快,但冲突多,行级冲突少,但速度慢.所以取了折衷的页级,一次锁定相邻的一组记录.
共享锁: 又叫做读锁. 当用户要进行数据的读取时,对数据加上共享锁.共享锁可以同时加上多个.
排他锁: 又叫做写锁. 当用户要进行数据的写入时,对数据加上排他锁.排他锁只可以加一个,他和其他的排他锁,共享锁都相斥.
用户的行为有两种,一种是来看房,多个用户一起看房是可以接受的. 一种是真正的入住一晚,在这期间,无论是想入住的还是想看房的都不可以.
死锁是指两个或多个事务在同一资源上相互占用,并请求锁定对方的资源,从而导致恶性循环的现象.
常见的解决死锁的方法
①.、如果不同程序会并发存取多个表,尽量约定以相同的顺序访问表,可以大大降低死锁机会.
如果业务处理不好可以用分布式事务锁或者使用乐观锁
数据库管理系统(DBMS)中的并发控制的任务是确保在多个事务同时存取数据库中同一数据时不破坏事务的隔离性和统一性以及数据库的统一性.乐观并发控制(乐观锁)和悲观并发控制(悲观锁)是并发控制主要采用的技术手段.
悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作.在查询完数据的时候就把事务锁起来,直到提交事务.实现方式:使用数据库中的锁机制
乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性.在修改数据的时候把事务锁起来,通过version的方式来进行锁定.实现方式:乐一般会使用版本号机制或CAS算法实现.
两种锁的使用场景:
从上面对两种锁的介绍,我们知道两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下(多读场景),即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量.
但如果是多写的情况,一般会经常产生冲突,这就会导致上层应用会不断的进行retry,这样反倒是降低了性能,所以一般多写的场景下用悲观锁就比较合适.
为了提高复杂SQL语句的复用性和表操作的安全性,MySQL数据库管理系统提供了视图特性.所谓视图,本质上是一种虚拟表,在物理上是不存在的,其内容与真实的表相似,包含一系列带有名称的列和行数据.但是,视图并不在数据库中以储存的数据值形式存在.行和列数据来自定义视图的查询所引用基本表,并且在具体引用视图时动态生成.
视图将我们不需要的数据过滤掉,将相关的列名用我们自定义的列名替换.视图作为一个访问接口,不管基表的表结构和表名有多复杂.
如果创建视图时不明确指定视图的列名,那么列名就和定义视图的select子句中的列名完全相同;
如果显式的指定视图的列名就按照指定的列名.
简化sql查询,提高开发效率.如果说还有另外一个用途那就是兼容老的表结构.
下面是视图的常见使用场景:
重用SQL语句;
简化复杂的SQL操作.在编写查询后,可以方便的重用它而不必知道它的基本查询细节;
使用表的组成部分而不是整个表;
保护数据.可以给用户授予表的特定部分的访问权限而不是整个表的访问权限;
更改数据格式和表示.视图可返回与底层表的表示和格式不同的数据.
优点
查询简单化.视图能简化用户的操作
数据安全性.视图使用户能以多种角度看待同一数据,能够对机密数据提供安全保护
逻辑数据独立性.视图对重构数据库提供了一定程度的逻辑独立性
缺点
性能.数据库必须把视图的查询转化成对基本表的查询,如果这个视图是由一个复杂的多表查询所定义,那么,即使是视图的一个简单查询,数据库也把它变成一个复杂的结合体,需要花费一定的时间.
修改限制.当用户试图修改视图的某些行时,数据库必须把它转化为对基本表的某些行的修改.事实上,当从视图中插入或者删除时,情况也是这样.对于简单视图来说,这是很方便的,但是,对于比较复杂的视图,可能是不可修改的
数据库表的设计依据,教我们怎么进行数据库表的设计.
第一范式: 要求任何一张表必须有主键,每一个字段原子性不可再分.第二范式: 建立在第一范式的基础之上,要求所有非主键字段完全依赖主键,不要产生部分依赖.第三范式: 建立在第二范式的基础之上,要求所有非主键字段直接依赖主键,不要产生传递依赖.
第一范式是最核心,最重要的范式,所有表的设计都需要满足.必须有主键,并且每一个字段都是原子性不可再分.
+----+----------+-------------------+----------+------+
| id | name | email | password | age |
+----+----------+-------------------+----------+------+
| 1 | ivan | ivan@q.com | 123345 | 23 |
| 2 | lee | iveeean@q.com | 123345 | 23 |
| 3 | sdsdslee | ivsdsdeeean@q.com | 123345 | 23 |
| 4 | regina | regina@qq.com | 123455 | 23 |
+----+----------+-------------------+----------+------+
id就是主键,并且每一个字段不可再分!
触发器是用户定义在关系表上的一类由事件驱动的特殊的存储过程.触发器是指一段代码,当触发某个事件时,自动执行这些代码.
使用场景
可以通过数据库中的相关表实现级联更改.实时监控某张表中的某个字段的更改而需要做出相应的处理.例如可以生成某些业务的编号.注意不要滥用,否则会造成数据库及应用程序的维护困难.
Before Insert
After Insert
Before Update
After Update
Before Delete
After Delete
Innodb引擎:Innodb引擎提供了对数据库ACID事务的支持.并且还提供了行级锁和外键的约束.它的设计的目标就是处理大数据容量的数据库系统.
MyIASM引擎(原本Mysql的默认引擎):不提供事务的支持,也不支持行级锁和外键.
以上就是土嘎嘎小编为大家整理的mysql面试小结相关主题介绍,如果您觉得小编更新的文章只要能对粉丝们有用,就是我们最大的鼓励和动力,不要忘记讲本站分享给您身边的朋友哦!!