02 数据库 索引 sql调优 锁 事务

目录

索引管理

面试:为什么要使用索引?

面试:什么样的信息能够成为索引?

面试:数据库索引可以使用那些数据结构?

索引的数据结构

面试:讲一讲二叉查找树

面试:讲一讲平衡二叉树

面试:讲一讲2-3树

面试:讲一讲红黑树

面试:讲一讲B树

面试:讲一讲B+树

面试:说说B树和B+树有啥区别?or 为什么数据库的索引选择使用B+树?

面试:讲一讲Hash索引

面试:讲一讲BitMap索引 or 如何快速的根据性别来查询数据库?

面试:密集索引和稀疏索引的区别

MySQL的两种存储引擎

面试:联合索引的最左匹配原则的成因

面试:索引是加的越多越好吗?

面试:SQL调优 or 如何定位并优化慢查询SQL?

步骤

开启慢查询

explain

面试:MyISAM和InnoDB关于锁方面的区别是什么?

读锁和写锁

数据库锁的分类

事务

事务操作

面试:数据库事务的四大特性

面试:事务的隔离级别,以及各级别下的并发访问问题

面试:innoDB可重复度隔离级别下,如何避免幻度?

面试:RC、RR级别下的innoDB的非阻塞读如何实现?

面试:MyISAM和InnoDB的区别?

关键语法


  1. 索引管理

    1. 面试:为什么要使用索引?

      1. 当我们使用最简单的方式查询的时候,会把表中所有的数据全部或分批次加载进内存,然后遍历找出我们需要的数据,当表中的数据比较少的时候这种查询速度是比较快的,但多的时候就不行了,所以要使用索引
      2. 索引就像字典中的目录一样,把那些关键的信息组织起来形成索引,像偏旁部首一样,这样根据索引就可以很快的查找到我们需要的数据
    2. 面试:什么样的信息能够成为索引?

      1. 主键
    3. 面试:数据库索引可以使用那些数据结构?

      1. 可以使用B+树

      2. 也可以使用hash结构进行查找
      3. 也可以使用BitMap索引
      4. 目前主流数据库索引是B+树,比较小众的是Hash和BitMap
    4. 索引的数据结构

      1. 面试:讲一讲二叉查找树

        1. 二叉查找树的特点是根结点比左边的大,比右边的小,查询的速度比较快,但是他也有它的缺点,比如说你频繁的向树中插入一个大值,那么这会增加树的深度,就会降低查找的效率,因为你要频繁的访问下一个子结点,频繁的产生IO,这就会降低查询的效率,所以我们就要想办法把树的高度变矮一些
      2. 面试:讲一讲平衡二叉树

        1. 平衡二叉树的目的是为了降低树的高度,进而提高检索数据的效率。常见的平衡二叉树有:2-3树、红黑树、B树、B+树。对于不同的平衡二叉树,他们平衡化使用的方法也不一样
      3. 面试:讲一讲2-3树

        1. 2-3树的特点是,一个树节点可以放置两个键值对,可以有三个子节点,在这个树的结点中,键值对也是有序的,在插入新数据的时候,如果说一个节点中出现的三个键值对,那么他就会把中间的那个键值对往上提,所以说,2-3树的相比于普通二叉树的一个特点就是,2-3树是从下往上生长的
      4. 面试:讲一讲红黑树

        1. 红黑树和2-3差不多,只是红黑树中一个结点不能再放两个键值对了,而是引入了红链接和黑链接,其中黑链接和普通的二叉树链接是一样的,而红链接就是2-3树的3-结点,一个红链接连接两个树节点,这两个树节点就组成了一个3-结点。
        2. 红黑树的红链接具有如下特性:一是红链接只能出现在左边、二是不能出现两个连续的红链接,如果出现了就变成4-结点了
        3. 红黑树既然是平衡二叉树那就要能降低树的高度,这也就是平衡化,红黑树的平衡化有三种方法,左旋、右旋、颜色翻转。当我们检测到树中右边出现了红链接就会使用左旋,出现了两个连续的红链接就会使用右旋,使用右旋之后,一个结点的左右节点都会变成红链接,这个时候我们在使用颜色统一即可。
      5. 面试:讲一讲B树

        1. 我们之前说的2-3树、红黑树其实就是一个3阶B树,假如说一个B树的阶是m,那么就允许一个树的结点最多拥有m个子结点,一个节点中允许最多拥有m-1个键值对信息,根结点至少有两个子结点,其他节点至少有ceil(m/2)个子结点,所有的叶子结点都是位于同一层的。
        2. 因为B树是一个平衡二叉树,在插入新数据的时候就不能出现线性的情况,B树可以通过分裂、合并、上移结点、下移结点来平衡化二叉树
      6. 面试:讲一讲B+树

        1. B+树和B树区别并不大,唯一的区别就是,B+树的非叶子结点是不存储具体的数据的,只存储数据的key,数据是存储在叶子结点中的,在每一个叶子节点都有一个指针指向下一个叶子结点,使这些叶子结点能够有序的连接在一起
      7. 面试:说说B树和B+树有啥区别?or 为什么数据库的索引选择使用B+树?

        1. B+树磁盘读取代价更低。B+树的给叶子结点存储的仅仅是数据的key,相比B树,在使用相同容量内存的情况下,B+树可以一次读取更多的索引节点,这样就间接减少了磁盘IO的次数,进而提高了查询的速度
        2. B+树查询效率更加稳定。因为B+树中只有叶子结点才会存储数据,所以无论检索什么数据都需要从根结点开始检索到叶子结点,所以说无论存进去的是什么数据,他们的查询次数都是一样的,所以说B+树的查询效率更加稳定
        3. B+树更有利于进行区间查询。因为B+树叶子结点是相互连接成一个有序的链,所以在B+树中,如果我们想要遍历某一个区间的话,我们只需要在叶子结点中遍历即可。而在B树中则需要对每一层的结点进行递归遍历
      8. 面试:讲一讲Hash索引

        1. Hash索引是根据要查询的字段,使用hash函数求出hash值,然后拿着hash值直接去bucket中去找,理论上,Hash索引的查找速度是比B+树快的,但事实上,这仅限于一些等值的查询操作,而对于一些范围查询Hash索引就无能为力。
        2. 而且数据库也无法根据Hash索引来给数据排序
        3. 当出现大量Hash值相等的情况时,Hash索引的检索速度也未必比B+树快
      9. 面试:讲一讲BitMap索引 or 如何快速的根据性别来查询数据库?

        1. BitMap索引又叫做位图索引,对于一个字段的取值只有固定的那几个的话,例如性别、颜色,BitMap索引是具有极高的查询效率的。在位图中,假如这个字段是性别,那么他只需要两行的01就可以代表所有的性别取值了,而01仅仅需要一位就可以代表,所以它占用的内存是极低的,查询的效率特别高
        2. 位图索引有一个特别大的缺陷,就是他的锁的粒度特别的大。当进行CRUD操作的时候需要将整个位图锁住,因为某一行可能会因为添加和删除数据而发生改变,所以,BitMap索引不适合那些并发量比较大的数据
    5. 面试:密集索引和稀疏索引的区别

      1. 密集索引和稀疏索引其实都是B+树索引,他们的区别在于叶子结点
        1. 密集索引:叶子结点不仅包括键值对信息,也包括这整条记录的其他信息
        2. 稀疏索引:叶子结点仅仅包括键位信息,以及该行记录的位置信息
      2. 优缺点
        1. 密集索引:查询的时间快,但是占用的存储空间大
        2. 稀疏索引:查询的时间慢一点,但占用的空间小
      3. MySQL的两种存储引擎

        1. MyISAM
          1. 使用的是稀疏索引
          2. 在MyISAM中,所有的索引(主键索引、外键索引、唯一建索引、普通索引)都是稀疏索引
        2. innoDB
          1. 使用的是密集索引
          2. 有且仅有一个密集索引
          3. 建立密集索引的原则
            1. 如果你自己定义的有主键、则该主键作为密集索引
            2. 若该主键没有被定义,则该表的第一个唯一非空索引作为密集索引
            3. 如果上面的两个条件都不满足,则innodb内部会生成一个隐藏主键(DB_ROW_ID),使用这个隐藏主键来建立密集索引
        3. 使用不同的存储引擎在创建文件时会有什么区别?
          1. 密集索引的索引和数据是存储在同一个文件中的,稀疏索引的索引和数据是分开存储的
            1. 建立一个MyISAM引擎的数据表test1会建立三个文件
              1. test1.frm   存储表的结构信息
              2. test1.MYI  存储表的索引信息
              3. test1.MYD 存储表的数据
            2. 建立一个InnoDB引擎的数据表 test2 会建立两个文件
              1. test2.frm 存储表的结构信息
              2. test2.ibd 存储表的数据和索引
    6. 面试:联合索引的最左匹配原则的成因

      1. 如果你的查询条件包括的是a和c那么MySQL无论如何优化你的查询条件也是无法使用上面的联合索引的,如果你的查询条件是a和b(和ab的顺序无关),那么是可以使用上面的联合索引的
      2. mysql会自动优化查询条件来匹配索引,来满足使用联合索引的条件。mysql在处理where条件时,优化查询条件一批匹配索引的位置,直到遇到范围查询(>、<、between、like)就停止匹配
      3. 当你建立一个联合索引KEY union_index (a,b,c)时,就相当于MySQL会先根据a排序,然后根据b排序,然后根据c排序,这就相当于建立了(a)、(a,b)、(a,b,c)三个索引
    7. 面试:索引是加的越多越好吗?

      1. 数据量小的表不需要建立索引,会增加额外的开销
      2. 过多的索引会增加维护索引的成本,因为数据变更也需要变更索引
      3. 更多的索引意味着需要更多的空间
  2. 面试:SQL调优 or 如何定位并优化慢查询SQL?

    1. 步骤

      1. 根据慢日志定位到慢查询SQL
      2. 使用explain工具分析SQL语句
      3. 修改SQL,或者让SQL尽量走索引
    2. 开启慢查询

      1. 02 数据库 索引 sql调优 锁 事务_第1张图片
      2. 02 数据库 索引 sql调优 锁 事务_第2张图片
      3. 注意:
        1. 直接在查询里面开启慢查询记录的话,下次重启数据库的时候还会还原,如果想要永久生效的话,需要修改里面的配置文件
    3. explain

      1. 直接放在select语句的前面即可
      2. 可以帮助我们分析查询低下的原因
      3. 关键字
        1. type
          1. all
            1. 查询走的是全表扫描
          2. index
            1. 查询走的是索引
            2. 索引更快一些
        2. extra
          1. 值为Using filesort或Using temporary查询起来是比较慢的
          2. 值为Using index是查询起来比较快的
    4. SQL优化
      1. 想办法让SQL语句走索引就行了
      2. 强制索引
        1. 在innoDB的存储引擎中,有些sql语句会使用主键索引(密集索引),MySQL默认使用的索引未必是最快的索引,这个时候就可以使用强制索引来修改查询时使用的索引
        2. 在select语句的最后面加上force index(name),稀疏索引的速度是比密集索引快的
    1. 面试:MyISAM和InnoDB关于锁方面的区别是什么?

      1. MyISAM默认使用的是表级锁,不支持行级锁
      2. innoDB默认使用行级锁,也支持表级锁
        1. 表级锁:在你执行一个查询语句的时候,MySQL会把整张表锁住
        2. 行级锁:在你执行一个查询操作的时候,MySQL仅仅把查询语句涉及到的行给锁住
          1. eg:select * from table where id between 1 and 10;
            1. 只会锁住1到10行
        3. 行级锁的缺点
          1. 锁的粒度越小,代价越高
          2. 行级锁需要扫描到那一行,然后对其上锁
      3. 两种引擎的适用场景
        1. MyISAM
          1. 频繁执行全表count的语句
            1. MyISAM中有一个变量去专门存储表的记录数,InnoDB则需要遍历表才行
          2. 对数据进行增删改的次数不多,查询非常频繁的
          3. 不需要事务
          4. 使用的是表级锁
        2. InnoDB
          1. 数据的增删改查都相当频繁的
            1. InnoDB加的是行级锁,不容易引起数据的阻塞,而MyISAM加的是表级锁,容易引起数据阻塞
          2. 可靠性要求比较高,要求支持事务
    2. 读锁和写锁

      1. 读锁
        1. 又叫共享锁
        2. 已经加了读锁的表或行,别的会话可读不可写
      2. 写锁
        1. 又叫排它锁
        2. 已经加了写锁的表或行,别的会话不可读不可写
    3. 数据库锁的分类

      1. 按照锁的粒度划分,表级锁、行级锁、页级锁
        1. 页级锁
          1. 是介于表级锁和行级锁之间的锁
          2. 只要很少用到的BDB存储引擎支持页级锁
      2. 按照锁的级别可以划分为共享锁、排它锁
      3. 按照操作划分,可分为DML锁、DDL锁
        1. 对表中的数据操作使用DML锁
        2. 对表的结构操作使用DDL锁
      4. 按照使用方式划分,可分为乐观锁、悲观锁
        1. 悲观锁
          1. 先加锁,然后在进行数据操作
          2. 更加安全
        2. 乐观锁
          1. 先操作数,在最后提交的时候再加锁
          2. 实现乐观锁的两种方式
            1. 版本号
              1. 在读取数据的时候会获取到记录的版本号,在操作完数据提交的时候会和现在数据的版本号作对比,如果说刚开始读取到的包版本号和现在记录中的版本号相同则代表可以更新数据,更新完之后会让版本号加一,如果说版本号不一样,就代表数据已经过时了,更新失败
            2. 时间戳
  3. 事务

    1. 事务操作

      1. 查看当前事务隔离级别:SELECT @@tx_isolation;
      2. 修改当前事务隔离级别:set session transaction isolation level read committed;
    2. 面试:数据库事务的四大特性

      1. ACID
      2. 原子性
        1. 要么全部失败回滚,要么全部成功执行最后提交
      3. 一致性
        1. 举个例子,A向B转账,B向A转账,AB无论如何转账,最后他俩的钱加起来总是不变的
      4. 隔离性
        1. 是指多个事务并发的执行时,一个事务不应该影响到其他事务
      5. 持久性
        1. 一个事务一旦提交,那么它对数据库的修改就应该永久保存在数据库中
        2. 持久性确保在数据库发生故障时,能够恢复已经提交的事务
    3. 面试:事务的隔离级别,以及各级别下的并发访问问题

      1. 更新丢失
        1. 一个事务正在更新数据,别的事务就不能同时更新这个数据
        2. 现在MySQL的所有隔离级别都可以避免这个问题了
      2. 脏读
        1. 一个事务读到了别的事务还没有提交的事务
        2. 可是使用read committed隔离级别来避免
          1. 最低的事务隔离级别是read uncommitted
          2. oracle默认的事务隔离级别是read committed
      3. 不可重复度
        1. 一个事务在查询一个数据的时候,并不知道自己查询出来的是不是最终的正确结果
        2. 有可能你查询的时候结果为1,等你查完了别的事务把结果更新为2了,其实2才是正确的结果,而你查询出来的那个1就是错误的结果
        3. 可使用repeatable read隔离级别来避免
          1. InnoDB默认的隔离级别就是这个
          2. 我在使用这个数据的时候,别的事务是无法更新这个数据的,只有等到当前事务提交了之后才行
      4. 幻读
        1. 事务a读取与搜索条件相符合的若干行,事务b以删除或插入的方式修改事务a的结果集,使事务a好想出现了幻觉一样
        2. 例如:事务a正在对全表进行一个更新操作,而事务b却想往表中插入一个记录,那么事务a以为自己修改了n条记录,而事实上自己修改了n+1条记录,这就是幻读
        3. 可以使用serializable隔离级别来避免
          1. 事务a在对自己的结果集进行操作的时候,事务b如果想修改事务a的结果集,那么事务b只能等待事务a提交了之后才能进行
      5. 面试:为啥不直接把所有表事务隔离级别设置为最高的?这样就可以避免上面的所有问题了
        1. 事务的隔离级别越高,事务安全性也越高,但是这会降低表的并发性,因为隔离级别越高,那么在进行操作的锁住的数据也就越多,容易产生数据阻塞,也就降低了数据库的效率
  4. 面试:innoDB可重复度隔离级别下,如何避免幻度?

    1. RR级别下避免幻读主要靠的是next-key
    2. next-key
      1. 行锁
      2. gap锁
        1. 会锁住一个范围,防止两次当前读出现幻读的情况
        2. gap锁可以防止插入引起的幻读 
        3. 加gap锁的条件
          1. 如果where条件全部命中,则不加gap锁,而是加行锁
          2. where条件部分命中或全都不命中才加gap锁
          3. 如果where条件不走索引的话,那么整张表都会加gap锁
            1. 这种加锁的代价太大,一般都是需要避免的
        4. 比如说:我的where条件是“in 1 2 3”,而实际只有1和2符合条件,那这个时候就会加上gap锁,123周围都会被锁住,假如这个时候你insert一个3那你就会被block住。如果说123都被满足了,那么加的就是行级锁。
  5. 面试:RC、RR级别下的innoDB的非阻塞读如何实现?

    1. 这个问题问的其实是快照读的底层实现原理
    2. 先了解当前读和快照读
      1. 当前读
        1. 使用当前读的语句
          1. select...lock in share mode、select...for update、update、delete、insert
          2. 当这些语句执行的时候使用的当前读,获取的是数据库中最新的数据
        2. 不管你上的是共享锁还是排它锁,使用的都是当前读
      2. 快照读
        1. 简单的select操作,是不加锁的
          1. 前提是事务的隔离级别不是serializable才成立的
            1. serializable会自动为普通的select语句加上共享锁
        2. 快照读是为了提高并发性能的
        3. 快照读有可能读到的不是最新的版本
    3. 快照读的底层实现
      1. 表中除了存储真实的数据字段之外还有额外的数据字段,其中和快照读相关的就有三个关键的字段,分别是:DB_TRX_ID、DB_ROLL_PTR、DB_ROW_ID
        1. DB_TRX_ID
          1. 用来存储最近一次操作本条记录的事务id
          2. 新开启一个事务,事务的id就会递增,最新开启的事务的id是最大的 
        2. DB_ROLL_PRT
          1. 回滚指针
          2. 记录的是历史记录在undo日志里面的物理地址
          3. 回滚指针使用undo日志可以查看一条记录的其他历史版本
            1. 使用undo链可以找到满足条件的历史版本数据
            2. 02 数据库 索引 sql调优 锁 事务_第3张图片
        3. DB_ROW_ID
          1. 包含一个随着新行插入而自动递增的值
          2. InnoDB的表如歌既没有主键也没有唯一键的话,MySQL会为我们自动添加一个自动递增的DB_ROW_ID字段作为主键
  6. 面试:MyISAM和InnoDB的区别?

    1. 锁方面的区别
      1. 行级锁
      2. 表级锁
    2. 索引的区别
      1. 聚集索引
      2. 稀疏索引
    3. 适用场景不同
    4. 事务方面
      1. InnoDB支持事务,MyISAM不支持事务
  7. 关键语法

    1. SELECT c.student_id, s.name
      from student s,cores c
      where s.student_id=c.student_id
      GROUP BY c.student_id
      having count(s.student_id)<(select COUNT(*) FROM course)

       

    2. group by
      1. select后面出现的列要么是group by使用的列,要么是其他表的列,再要么是使用了聚合函数的列
      2. 底层原理
        1. group by会将划分出来的结果集缓存到临时表中,然后再使用聚合函数对这些结果集进行处理
    3. having
      1. 通常和group by语句一起使用
      2. 如果不和group by语句使用,那么它的作用就和where一样,支持where中的所有操作符
      3. where是用来过滤行的,having是用来过滤组的
      4. 出现顺序:where > group by > having

你可能感兴趣的:(Java面试,#,数据库)