数据库面经


一、Mysql的超键,候选键,主键,外键:

  (1)超键:在关系中能唯一标识元组的属性集称为超键,可以区分表中每一行记录的属性集(单个属性,多个属性组成也行)

    如:在一个学生的表中,假设有“学号”、“姓名”、“相关信息”、“生日”等字段, 其中学号是唯一的,那么(学号)是一个超键,同时(学号,姓名,生日)的组合也是唯一的,所以也可以为一个超键。反正记住一点,就是根据这些属性可以唯一确定一名学生的,就是超键。

  (2)候选键:候选键是在超键的基础上定义的,在要求可以区分每一行的基础上,同时是最小唯一的,即候选键中删除任何一个属性后就不能再区分每一行。

  (3)主键:从候选键中选出一个键就能区分每一行的就是主键.

  (4)外键:在关系模式(表)R中,属性a是其他模式的主键,则a是关系模式R中的外键.

二、数据库的索引:

  表Employee(Name,Age,Address)

  查询语句:SELECT * FROM Employee WHERE Name = 'Jesus'

  若无索引:运行这个查询,在查找名字为Jesus的雇员的过程中,数据库不得不从Employee表中的每一行并确定雇员的名字(Name)是否为 ‘Jesus’。由于我们想要得到每一个名字为Jesus的雇员信息,在查询到第一个符合条件的行后,不能停止查询,因为可能还有其他符合条件的行。所以,必须一行一行的查找直到最后一行-这就意味数据库不得不检查上千行数据才能找到所以名字为Jesus的雇员。这就是所谓的全表扫描

  使用索引如何提高性能:使用索引的全部意义就是通过缩小一张表中需要查询的记录/行的数目来加快搜索的速度。索引基本上是用来存储列值的数据结构,这使查找这些列值更加快速。如果索引使用最常用的数据结构-B+树-那么其中的数据是有序的。有序的列值可以极大的提升性能。我们在Name这一列上创建一个索引。这意味着当我们用之前的SQL查找姓名是‘Jesus’的雇员时,不需要再扫描全表。而是用索引查找去查找名字为‘Jesus’的雇员,因为索引已经按照按字母顺序排序。索引已经排序意味着查询一个名字会快很多,因为名字少字母为‘J’的员工都是排列在一起的。另外重要的一点是,索引同时存储了表中相应行的指针以获取其他列的数据。

   创建索引:CREATE INDEX name_index ON Employee (Employee_Name)

   创建联合索引:CREATE INDEX name_index ON Employee (Employee_Name, Employee_Age)

(1)什么是索引:一个索引是存储的表中一个特定列的值数据结构(最常见的是B+Tree和hash表)。索引是在表的列上创建。所以,要记住的关键点是索引包含一个表中列的值,并且这些值存储在一个数据结构中。请记住记住这一点:索引是一种数据结构 。

  1、MySQL的基本存储结构:页,记录都存储在页里面。

   1)各个数据页可以组成一个双向链表。

   2)每个数据页中的行记录组成单向链表。

   3)每个数据页都会为存储在它里边儿的记录生成一个页目录,在通过主键查找某条记录的时候可以在页目录中使用二分法快速定位到对应的槽,然后再遍历该槽对应分组中的记录即可快速找到指定的记录

   4)以其他列(非主键)作为搜索条件:只能从最小记录开始依次遍历单链表中的每条记录。

  2、为什么没有任何优化的查询慢:

   1)需要遍历双向链表,找到所在的页

   2)从所在的页内中查找相应的记录

   3)由于不是根据你主键查询,只能遍历所在的页的单链表。

  3、索引里存的是什么

   数据库索引并不存储这个表中其他列(字段)的值。举例来说,如果我们在Name列创建索引,那么列Age和Address上的值并不会存储在这个索引当中。如果我们确实把其他所有字段也存储在个这个索引中,那就成了拷贝一整张表做为索引-这样会占用太大的空间而且会十分低效。同时存储了指向表中的相应行的指针。指针是指一块内存区域, 该内存区域记录的是对硬盘上记录的相应行的数据的引用。

  4、何时使用索引

   数据库什么时候使用索引 - 数据库自己决定,当这个SQL (SELECT * FROM Employee WHERE Name = "Jesus" )运行时,数据库会检查在查询的列上是否有索引。假设Employee_Name列上确实创建了索引,数据库会接着检查使用这个索引做查询是否合理,若合理则使用索引.

   索引不应该用于小规模的表,当字段用于WHERE子句作为过滤器会返回表里的大部分记录时,该字段就不适合设置索引。经常被操作的字段不应该设置索引,因为对索引的维护会变得很繁重。

(2)什么样的数据结构可以作为MySQL索引:B+树和哈希表

  1、B+树索引

   B+树是最常用的用于索引的数据结构。因为它们是时间复杂度低, 查找、删除、插入操作都可以可以在对数时间内完成。另外一个重要原因存储在B+树中的数据是有序的

  2、数据库索引为什么用B+树而不用AVL、红黑树

   虽说AVL 树和红黑树这些二叉树结构的数据结构可以达到最高的查询效率,AVL树和红黑树常用于存储内存中的有序数据,增删很快.在大规模数据存储的时候,红黑树往往出现由于树的深度过大而造成磁盘IO读写过于频繁,进而导致效率低下的情况。B+树只有叶节点存放数据,其余节点用来索引,而B-树是每个索引节点都会有Data域。所以从Mysql(Inoodb)的角度来看,B+树是用来充当索引的,一般来说索引非常大,尤其是关系性数据库这种数据量大的索引能达到亿级别,所以为了减少内存的占用,索引也会被存储在磁盘上。 Mysql通过磁盘IO次数衡量查询效率.B-树/B+树 的特点就是每层节点数目非常多,层数很少,目的就是为了就少磁盘IO次数,但是B-树的每个节点都有data域(指针),这无疑增大了节点大小,说白了增加了磁盘IO次数(磁盘IO一次读出的数据量大小是固定的,单个数据变大,每次读出的就少,IO次数增多,一次IO多耗时),而B+树除了叶子节点其它节点并不存储数据,节点小,磁盘IO次数就少. B+树所有的Data域在叶子节点,一般来说都会进行一个优化,就是将所有的叶子节点用指针串起来。这样遍历叶子节点就能获得全部数据,这样就能进行区间访问.据磁盘查找存取的次数往往由树的高度所决定,所以,只要我们通过某种较好的树结构减少树的结构尽量减少树的高度,B树可以有多个子女,从几十到上千,可以降低树的高度。

  3、哈希索引

   使用哈希索引的原因是,在寻找值时哈希表效率极高。所以,如果使用哈希索引,对于比较字符串是否相等的查询能够极快的检索出的值。例如之前我们讨论过的这个查询(SELECT * FROM Employee WHERE Employee_Name = ‘Jesus’) 就可以受益于创建在Employee_Name 列上的哈希索引。哈系索引的工作方式是将列的值作为索引的键值(key),和键值相对应实际的值(value)是指向该表中相应行的指针。因为哈希表基本上可以看作是关联数组,一个典型的数据项就像“Jesus => 0x28939″,而0x28939是对内存中表中包含Jesus这一行的引用。在哈系索引的中查询一个像“Jesus”这样的值,并得到对应行的在内存中的引用,明显要比扫描全表获得值为“Jesus”的行的方式快很多。缺点是哈希表是无顺的数据结构,只适合查询键值对-也就是说查询相等的查询不适合比较大小的查询语句中.

(3)索引的特征:索引有两个特征,即唯一性索引和复合索引。

  1、唯一性索引保证索引列不包含重复数据,不会包含冗余数据;可以使用多个列,但是必须确保索引列中每个值组合都是唯一的。如果表中已经有一个主键约束或者唯一性键(可以是多个列)约束,那么当创建表或者修改表时,SQL Server自动创建一个唯一性索引。然而,如果必须保证唯一性,那么应该创建主键约束或者唯一性键约束,而不是创建一个唯一性索引。当创建唯一性索引 时,应该认真考虑这些规则:当在表中创建主键约束或者唯一性键约束时,SQL Server自动创建一个唯一性索引;如果表中已经包含有数据,那么当创建索引时,SQL Server检查表中已有数据的冗余性;每当使用插入语句插入数据或者使用修改语句修改数据时,SQL Server检查数据的冗余性:如果有冗余值,那么SQL Server取消该语句的执行,并且返回一个错误消息;确保表中的每一行数据都有一个唯一值,这样可以确保每一个实体都可以唯一确认;只能在可以保证实体 完整性的列上创建唯一性索引,例如,不能在人事表中的姓名列上创建唯一性索引,因为人们可以有相同的姓名。

  2、复合索引就是一个索引创建在两个列或者多个列上。在搜索时,当两个或者多个列作为一个关键值时,最好在这些列上创建复合索引。复合列的长度不能太长;在复合索引中,所 有的列必须来自同一个表中,不能跨表建立复合列;在复合索引中,列的排列顺序是非常重要的,因此要认真排列列的顺序,原则上,应该首先定义最唯一的列,例 如在(COL1,COL2)上的索引与在(COL2,COL1)上的索引是不相同的,因为两个索引的列的顺序不同.

  3、聚集索引和非聚集索引:

   1)聚集索引:在叶节点存放一整行记录的索引被称为聚簇索引,一个表中只能拥有一个聚集索引。

   2)非聚集索引:在叶节点存放一整行记录的索引被称为聚簇索引,其它称为非聚集索引,一个表中可以拥有多个非聚集索引。

   区别:索引的叶子节点就是对应的数据节点,聚集索引的速度往往会更快,非聚集索引叶节点仍然是索引节点,只是有一个指针指向对应的数据块,如果使用非聚集索引查询,若查询列中包含了其他列,而该索引没有覆盖的列,那么他还要回表进行二次查询,查询节点上对应的数据行的数据。

   非聚集索引在查询的时候可以的话就避免二次查询,这样性能会大幅提升:建立两列以上的索引,即可查询复合索引里的列的数据而不需要进行回表二次查询

  4、索引(复合索引)的最左匹配原则:最左优先,以最左边的为起点任何连续的索引都能匹配上,但是遇到范围查询(>、<、between、like)就会停止匹配。

   1)索引可以简单如一个列 (a),也可以复杂如多个列 (a,b,c,d),即复合索引。

   2)如果是联合索引,那么key也由多个列组成,同时,索引只能用于查找key是否存在(相等),遇到范围查询(>、<、between、like左匹配)等就不能进一步匹配了,后续退化为线性查找。

   3)列的排列顺序决定了可命中索引的列数

  例如:如有索引 (a,b,c,d),查询条件 a=1 and b=2 and c>3 and d=4,则会在每个节点依次命中a、b、c,无法命中d。(c已经是范围查询了,d肯定是排不了序了)

(4)索引的优缺点

  1、使用索引的优点:

   1)可以大大加快 数据的检索速度,这也是创建索引的最主要的原因。

   2)可以加速表和表之间的连接

   3)在使用分组和排序 子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。

   4)通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。

  2、使用索引的缺点:

   1)索引会占用空间 - 你的表越大,索引占用的空间越大

   2)性能损失(主要值更新操作)当你在表中添加、删除或者更新行数据的时候, 在索引中也会有相同的操作。记住:建立在某列(或多列)索引需要保存该列最新的数据。

  3、主键和唯一索引的区别:

   1)主键是一种约束,唯一索引是一种索引,两者在本质上是不同的。

   2)主键创建后一定包含一个唯一性索引,唯一性索引并不一定就是主键。

   3)唯一性索引列允许空值,而主键列不允许为空值。

   4)一个表最多只能创建一个主键,但可以创建多个唯一索引。

  4、Hash索引的优缺点:

   优点:

    采用一定的哈希算法,把键值换算成新的哈希值,检索时不需要像B+树那样从根节点到叶子节点逐级查找,只需一次哈希算法即可立刻定位到相应的位置,速度非常快。

   缺点:

    1)哈希索引也没办法利用索引完成排序

    2)不支持最左匹配原则

    3)在有大量重复键值情况下,哈希索引的效率也是极低的---->哈希碰撞问题。

    4)不支持范围查询

三、事务:

(1)事务的四个特性

  1、原子性(Atomic):事务包含的所有操作要么全部成功,要么全部失败回滚;成功必须要完全应用到数据库,失败则不能对数据库产生影响;

  2、一致性(Consistency)事务执行前和执行后必须处于一致性状态,例:用户A和用户B的前加起来一共是5000; 无论AB用户之间是如何相互转换的,事务结束后两个用户的钱加起来还是5000,这就是事务的一致性。

  3、隔离性(Isolation):当多个用户并发访问数据库时,数据库为每一个用户开启的事务,不被其他事务的操作所干扰,多个并发事务之间要相互隔离;

  4、持久性(Durability):一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的

(2)事务的隔离级别:

  隔离性:当多个线程都开启事务来操作数据库中的数据时,数据库系统要进行隔离操作,以保证各个线程获取数据的准确性。 不考虑事务的隔离性,会产生的几种问题:

  1、脏读:是指一个事务处理过程里读取了另一个未提交的事务中的数据,然后使用了这个数据;

  2、不可重复读:在一个事务内,多次读取同一个数据,在这个事务还没有结束 ,另一个事务也访问该同一数据,但是由于第二个事务的修改,那么第一个事务两次读取的数据可能不一样,因此称为不可重复读

  3、幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这好像发生了幻觉一样,这就叫幻读。

  不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表

  隔离级别:

  1、Read uncommitted(读未提交):最低级别,任何情况都会发生。级别最低,执行效率最高,读取未提交的数据被称为脏读。

  2、Read Committed(读已提交):可避免脏读的发生。

  3、Repeatable read(可重复读):可避免脏读、不可重复读的发生。Mysql的默认级别,级别最高,执行效率最低

  4、Serializable(串行化):避免脏读、不可重复读,幻读的发生。

(3)就前三种隔离级别进行场景设计:

01: Read uncommitted 读未提交; 公司发工资了,领导把5000元打到singo的账号上,但是该事务并未提交,而singo正好去查看账户,发现工资已经到账,是5000元整,非常高兴。可是不幸的是,领导发现发给singo的工资金额不对,是2000元,于是迅速回滚了事务,修改金额后,将事务提交,最后singo实际的工资只有2000元,singo空欢喜一场。

02:Read committed 读已提交; singo拿着工资卡去消费,系统读取到卡里确实有2000元,而此时她的老婆也正好在网上转账,把singo工资卡的2000元转到另一账户,并在singo之前提交了事务,当singo扣款时,系统检查到singo的工资卡已经没有钱,扣款失败,singo十分纳闷,明明卡里有钱,为何......

03:Repeatable read 重复读 当singo拿着工资卡去消费时,一旦系统开始读取工资卡信息(即事务开始),singo的老婆就不可能对该记录进行修改,也就是singo的老婆不能在此时转账。

四、数据库的4中引擎:

(1)MyISAM存储引擎:节点的data域存储的是数据地址,索引是索引,数据是数据。

 

(2)innoDB:data域存的是数据本身,索引也是数据。

 

(3)MyISAM与InnoDB的区别:

  1、MyISAM不支持事务,是非事务安全的,而InnoDB具有提交、回滚和崩溃恢复能力的事务安全

  2、MyISAM锁的粒度是表级的,不支持外键,而InnoDB支持行级锁,支持外键。

  3、MyISAM管理非事务表,提供高速搜索能力,如果在应用中执行大量select操作可选择

  4、InnoDB用于事务处理,具有ACID事务支持等特性,如果在应用中执行大量insert和update操作,可选择。

  5、支持3种不同的存储格式,分别是:静态表(表中的字段都是非变长字段,这样每个记录都是固定长度的,优点存储非常迅速,容易缓存,出现故障容易恢复;缺点是占用的空间通常比动态表多);动态表(记录不是固定长度的,这样存储的优点是占用的空间相对较少;缺点:频繁的更新、删除数据容易产生碎片,需要定期执行optimize table);压缩表(因为每个记录是被单独压缩的,所以只有非常小的访问开支)

(4)Memory存储引擎:Memory存储引擎使用存在于内存中的内容来创建表。每个memory表只实际对应一个磁盘文件,memory类型的表访问非常的快,默认使用HASH索引,但是一旦服务关闭,表中的数据就会丢失掉。

(5)Merge存储引擎:Merge存储引擎是一组MyISAM表的组合,这些MyISAM表必须结构完全相同,merge表本身并没有数据,对merge类型的表可以进行查询,更新,删除操作,这些操作实际上是对内部的MyISAM表进行的。

五、Mysql的查询优化:

 Mysql是如何执行查询的:

  (1)客户端发送一条查询给服务器;

  (2)服务器先检查查询缓存,如果命中了缓存,则立刻返回存储在缓存中的结果。否则进入下一阶段;

  (3)服务器进行SQL解析、预处理、在由查询优化器生成对应的执行计划;

  (4)MySQL根据优化器生成的执行计划,调用存储引擎的API来执行查询。

  (5)将结果返回给客服端,同时也会放入查询缓存中。

 如下图所示:

  

 六、SQL的优化

 驱动表:指定了联接条件时,满足查询条件的记录行数少的表为[驱动表]

     未指定联接条件时,行数少的表为[驱动表](Important!)

 永远用小结果集驱动大结果集(Important)

  优化查询:

  (1)重新定义关联表的顺序;小表放在前面,大表放在后面.

  (2)将外连接转化为内连接

  (3)优化器主要根据定义的索引来提高性能,可以设置索引, 避免在索引列上使用IS NULL和IS NOT NULL

  (4) 用IN来替换OR 

  (5)避免SELECT *,因为它会进行全表扫描,不能有效利用索引

  (6)分组group by 优化,默认情况下group by 对字段分组的时候,会排序

  (7)order by的列尽量索引.使用limit来实现分页逻辑.

  (8)比较运算符能用 “=”就不用“<>”,“=”增加了索引的使用几率


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM