• 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏吧

MySQL面试互问

互联网 diligentman 1周前 (10-18) 9次浏览

MySQL

数据库指定哪些索引,都说说

普通索引,唯一索引,主键索引,全文索引

使用索引的优点

  • 提高数据的搜索速度
  • 加快表与表之间的连接速度
  • 在信息检索过程中,若使用分组及排序子句进行时,通过建立索引能有效的减少检索过程中所需的分组及排序时间,提高检索效率。

使用索引的缺点

  • 在我们建立数据库的时候,需要花费的时间去建立和维护索引,而且随着数据量的增加,需要维护它的时间也会增加。
  • 在创建索引的时候会占用存储空间
  • 在我们需要修改表中的数据时,索引还需进行动态的维护,所以对数据库的维护带来了一定的麻烦。

唯一索引: 在创建唯一索引时要不能给具有相同的索引值
主键索引: 在我们给一个字段设置主键的时候,它就会自动创建主键索引,用来确保每一个值都是唯一的
聚集索引: 我们在表中添加数据的顺序,与我们创建索引值相同,而且一个表中只能有一个聚集索引
普通索引: 它的结构主要以B+树和哈希索引为主,主要是对数据表中的数据进行精确查找
全文索引: 它的作用是搜索数据表中的字段不是包含我们的关键字,就像索引引擎中的模糊查询。


什么是回表知道吗

比如一个数据库索引有一级索引和二级索引,二级索引叶子节点存储的是主键,一级索引存储的是主键和数据,通过二级索引查找到主键后再到一级索引通过已知主键查找数据,需要查找两次,这就是索引。


非聚集索引一定会回表查询吗?

不一定,这涉及到查询语句所要求的字段是否命中了索引,如果全部命中了索引,那么就不必要再进行回表查询。
举个简单的例子:假设我们在员工表的年龄上建立了索引,那么当进行 select age from employee where age < 20 的查询时,在索引的叶子节点上,已经包含了age信息,不会再次进行回表查询


知道联合索引为什么要注意索引的顺序吗?

MySQL使用索引时需要索引有序,假设现在建立了”name,age,school“的联合索引,那么索引的排序为:先按照name排序,如果name相同,则按照age排序,如果age的值相等,则按照school进行排序,当进行查询时,此时索引仅仅按照严格有序,因此必须首先使用name字段进行等值查询,之后对于匹配到的列而言,其按照age字段严格有序,此时可以使用age字段做索引查询…以此类推,因此建立联合索引的时候应该注意索引列的顺序,一般情况下,将查询需求频繁或者字段高的列放在前面,此外可以根据带列的查询或者表结构进行单独的调整。


数据库事务的四大特性

A=Atomicity
原子性,一个事务要么全部成功 ,要么全部失败。不可能只执行一部分操作
C=Consistency
一致性,系统(数据库)总是从一个一致性状态移到另一个一致性状态,不会存在中间态
所有事务对数据的读取都是一致性的。
I=Isolation
隔离性:通常来说,一个事务未完全提交之前,对其他事务是不可见的。
D=Durability
持久性,一旦事务提交,那么就永远是这样子,那么数据库奔溃,写入磁盘中


多个事务同时进行时会造成什么问题?

脏读:A事务读取到了B事务未提交的内容,而B事务后面进行了回滚
不可重复读:当设置A事务只能读取B事务已经提交的部分,会造成A事务内的两次查询,结果竟然不一样,因为在此期间B事务进行了操作
幻读:A事务读取了一个范围的内容,而同时B事务在此期间插入了一条数据,造成幻觉


如何解决以上的问题呢

MySQL的四种隔离级别如下:
未提交读(READ UNCOMMITTED)

这就是上面所说的例外情况了,这个隔离级别下,其他事务可以看到本事务没有提交的部分修改.因此会造成脏读的问题(读取到了其他事务未提交的部分,而之后该事务进行了回滚).

这个级别的性能没有足够大的优势,但是又有很多的问题,因此很少使用.

已提交读(READ COMMITTED)

其他事务只能读取到本事务已经提交的部分.这个隔离级别有 不可重复读的问题,在同一个事务内的两次读取,拿到的结果竟然不一样,因为另外一个事务对数据进行了修改.

REPEATABLE READ(可重复读)

可重复读隔离级别解决了上面不可重复读的问题(看名字也知道),但是仍然有一个新问题,就是 幻读,当你读取id> 10 的数据行时,对涉及到的所有行加上了读锁,此时例外一个事务新插入了一条id=11的数据,因为是新插入的,所以不会触发上面的锁的排斥,那么进行本事务进行下一次的查询时会发现有一条id=11的数据,而上次的查询操作并没有获取到,再进行插入就会有主键冲突的问题.

SERIALIZABLE(可串行化)

这是最高的隔离级别,可以解决上面提到的所有问题,因为他强制将所以的操作串行执行,这会导致并发性能极速下降,因此也不是很常用.

对MySQL有了解吗?

从锁的类别上来讲,有共享锁和排他锁.

  • 共享锁: 又叫做读锁. 当用户要进行数据的读取时,对数据加上共享锁.共享锁可以同时加上多个.
  • 排他锁: 又叫做写锁. 当用户要进行数据的写入时,对数据加上排他锁.排他锁只可以加一个,他和其他的排他锁,共享锁都相斥.
    用上面的例子来说就是用户的行为有两种,一种是来看房,多个用户一起看房是可以接受的. 一种是真正的入住一晚,在这期间,无论是想入住的还是想看房的都不可以.
    锁的粒度取决于具体的存储引擎,InnoDB实现了行级锁,页级锁,表级锁.
    他们的加锁开销从大大小,并发能力也是从大到小.

为什么不使用UUID?

因为在InnoDB存储引擎中,主键索引是作为聚簇索引存在的,也就是说,主键索引的B+树叶子节点上存储了主键索引以及全部的数据(按照顺序),如果主键索引是自增ID,那么只需要不断向后排列即可,如果是UUID,由于到来的ID与原来的大小不确定,会造成非常多的数据插入,数据移动,然后导致产生很多的内存碎片,进而造成插入性能的下降.


固定长度的字符串比如身份证号应该用什么字段存储好呢,说说原因。

用户身份证号等固定长度的字符串应该使用char而不是varchar来存储,这样可以节省空间且提高检索效率.

char是一个定长字段,假如申请了char(10)的空间,那么无论实际存储多少内容.该字段都占用10个字符,而varchar是变长的,也就是说申请的只是最大长度,占用的空间为实际字符长度+1,最后一个字符存储使用了多长的空间.

在检索效率上来讲,char > varchar,因此在使用中,如果确定某个字段的值的长度,可以使用char,否则应该尽量使用varchar.例如存储用户MD5加密后的密码,则应该使用char.


InnoDB和MyISAM的区别?


关心过业务系统里面的sql耗时吗?一般你会怎么考虑优化?

在业务系统中,除了使用主键进行的查询,其他的我都会在测试库上测试其耗时,慢查询的统计主要由运维在做,会定期将业务中的慢查询反馈给我们.
慢查询的优化首先要搞明白慢的原因是什么? 是查询条件没有命中索引?是load了不需要的数据列?还是数据量太大?
所以优化也是针对这三个方向来的:
首先分析语句,看看是否load了额外的数据,可能是查询了多余的行并且抛弃掉了,可能是加载了许多结果中并不需要的列,对语句进行分析以及重写.
分析语句的执行计划,然后获得其使用索引的情况,之后修改语句或者修改索引,使得语句可以尽可能的命中索引.
如果对语句的优化已经无法进行,可以考虑表中的数据量是否太大,如果是的话可以进行横向或者纵向的分表.


表设计的时候遵循范式,说一说三个范式。

第一范式: 每个列都不可以再拆分. 第二范式: 非主键列完全依赖于主键,而不能是依赖于主键的一部分. 第三范式: 非主键列只依赖于主键,不依赖于其他非主键.

  在设计数据库结构的时候,要尽量遵守三范式,如果不遵守,必须有足够的理由.比如性能. 事实上我们经常会为了性能而妥协数据库的设计.


喜欢 (0)