mysql面试题总结 史上最全的数据库面试题,不看绝对后悔

  1. Mysql中的myisam与innodb的区别?
  2. InnoDB存储引擎的四大特性?
  3. 什么是事务?
  4. 数据库事务的四大特性?
  5. 不考虑事务的隔离性,会发生几种问题?
  6. MySQL数据库提供的四种隔离级别?
  7. 有多少种日志?
  8. 事务是如何通过日志来实现的?
  9. 数据库的乐观锁和悲观锁是什么?
  10. 什么是存储过程?有哪些优缺点?
  11. 存储过程与触发器的区别?
  12. 索引是什么?有什么作用以及优缺点?
  13. 说一说MySQL数据库几个基本的索引类型?
  14. 使用索引查询一定能提高查询的性能吗?为什么?
  15. 为数据表建立索引的原则有哪些?
  16. 什么情况下应不建或少建索引?
  17. 什么是mysql联合索引?
  18. 说一说 B+树索引、哈希索引?
  19. B树和B+树的区别?
  20. 为什么说B+比B树更适合实际应用中操作系统的文件索引和数据库索引?
  21. 聚集索引和非聚集索引区别?
  22. 说一说drop、deletetruncate的区别?
  23. drop、deletetruncate分别在什么场景之下使用?
  24. 超键、候选键、主键、外键分别是什么?
  25. mysql为什么用自增列作为主键?
  26. MySQL中的varchar和char的区别以及varchar(50)中的50代表的涵义?
  27. 什么是视图?视图的使用场景有哪些?
  28. 数据库三大范式?
  29. sql优化
  30. 非关系型数据库和关系型数据库区别,优势比较?
  31. 什么是 内连接、外连接、交叉连接、笛卡尔积等?
  32. SQL语言分类
  33. like %和-的区别
  34. count(*)、count(1)、count(column)的区别
  35. 你们数据库是否支持emoji表情,如果不支持,如何操作?
  36. 你是如何监控你们的数据库的?你们的慢日志都是怎么查询的?

1、Mysql中的MyISAM与InnoDB的区别?

(1)InnoDB存储引擎支持事务,而MyISAM不支持事务;

(2)InnoDB支持行级锁,而MyISAM只支持表级锁;

( InnoDB行锁是通过给索引加锁实现的,即只有通过索引条件检索数据,InnoDB才使用行级锁,否则将使用表级锁!行级锁在每次获取锁和释放锁的操作需要比表级锁消耗更多的资源。

MySQL表级锁有两种模式:表共享读锁和表独占写锁。就是说对MyIASM表进行读操作时,它不会阻塞其他用户对同一表的读请求,但会阻塞对同一表的写操作;而对MyISAM表的写操作,会阻塞其他用户对同一表的读和写操作。)

(3)InnoDB支持外键,而MyISAM不支持外键;

(4)InnoDB不保存数据库表中表的具体行数,而MyISAM会保存;

( 也就是说,执行 select count(*) from table 时,InnoDB要扫描一遍整个表来计算有多少行,而MyISAM只需要读出保存好的行数即可(内部维护了一个计算器,可以直接调取)。【注】:当count(*)语句包含where条件时,两种表的操作是一样的。也就是上述介绍到的InnoDB使用表锁的一种情况。)

 

  对于select ,update ,insert ,delete 操作:

  如果执行大量的SELECT,MyISAM是更好的选择(因为MyISAM不支持事务,使得MySQL可以提供高速存储和检索,以及全文搜索能力)

  如果执行大量的INSERT或UPDATE,出于性能方面的考虑,应该使用InnoDB表(因为InnoDB支持事务,在一些列增删改中只要哪个出错还可以回滚还原,而MyISAM就不可以了)

2、InnoDB存储引擎的四大特性?

插入缓冲、二次写、自适应哈希索引、预读

(1)插入缓冲

  一般情况下,主键是行唯一的标识符。通常应用程序中行记录的插入顺序是按照主键递增的顺序进行插入的。因此,插入聚集索引一般是顺序的,不需要磁盘的随机读取。因为,对于此类情况下的插入,速度还是非常快的。

  如果索引是非聚集的且不唯一,在进行插入操作时,数据的存放对于非聚集索引叶子节点的插入不是顺序的,这时需要离散地访问非聚集索引页,由于随机读取的存在而导致了插入操作性能下降。(这是因为B+树的特性决定了非聚集索引插入的离散性。)

  插入缓冲对于非聚集索引的插入和更新操作,不是每一次直接插入索引页中,而是先判断插入的非聚集索引页是否在缓存池中。如果在,则直接插入;如果不在,则先放入一个插入缓冲区中,好似欺骗数据库这个非聚集的索引已经插入到叶子结点了,然后再以一定的频率执行插入缓冲和非聚集索引页子节点的合并操作,这时通常能将多个插入合并到一个操作中(因为在一个索引页中),这就大大提高了对非聚集索引执行插入和修改操作的性能

    插入缓冲的使用要满足两个条件

  • 索引是辅助索引
  • 索引不是唯一的
    • (辅助索引不能是唯一的,因为在把它插入到插入缓冲时,我们并不去查找索引页的情况。如果去查找肯定又会出现离散读的情况,插入缓冲就失去了意义。)

    存在的问题:

      在写密集的情况下,插入缓冲会过多的占用缓冲池内存,默认情况下最大可以占用1/2的缓冲池内存。

(2)二次写

当数据库宕机时,可能发生数据库正在写一个页面,而这个页只写了一部分的情况,我们称之为部分写失效。当写入失效发生时,先通过页的副本来还原该页,再重做日志,这就是两次写

doublewrite步骤:

  1. 当一系列机制(main函数触发、checkpoint等)触发数据缓冲池中的脏页进行刷新时,并不直接写磁盘,而是会通过memcpy函数将脏页拷贝到内存中的doublewrite buffer,之后通过doublewrite buffer再分两次、每次1MB顺序写入共享表空间的物理磁盘上。
  2. 然后马上调用fsync函数,同步脏页进磁盘。在这个过程中,doublewrite页的存储是连续的,因此写入磁盘为顺序写,性能很高在完成doublewrite页的写入后,再将doublewrite buffer中的页写入到各个表空间文件中,此时的写入则是离散的。

  如果操作系统在将页写入磁盘的过程中崩溃了,在恢复过程中,InnoDB存储引擎可以从共享表空间中的doublewrite中找到该页的一个副本,将其拷贝到表空间文件,再应用重做日志,就完成了恢复过程。因为有副本所以也不担心表空间中数据页是否损坏。

(3)自适应哈希索引

  InnoDB存储引擎会监控对表上索引的查找,如果观察到建立哈希索引可以带来速度的提升,则建立哈希索引,所以称为自适应的。自适应哈希索引通过缓冲池的B+树构造而来,因此建立的速度很快,而且不需要将整个表都建哈希索引,InnoDB存储引擎会自动根据访问的频率和模式来为某些页建立哈希索引。

  (4)预读

  InnoDB 提供了两种预读的方式,一种是 Linear read ahead,由参数innodb_read_ahead_threshold控制,当你连续读取一个 extent 的 threshold 个 page 的时候,会触发下一个 extent 64个page的预读。另外一种是Random read-ahead,由参数innodb_random_read_ahead控制,当你连续读取设定的数量的page后,会触发读取这个extent的剩余page。
  InnoDB 的预读功能是使用后台线程异步完成的。

3、什么是事务?

  事务就是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。事务是数据库维护数据一致性的单位,在每个事务结束时,都能保持数据一致性。

4、数据库事务的四大特性?

  原子性、一致性、隔离性、持久性  (ACID)

  • 原子性:是指整个数据库事务是不可分割的单位。只有使事务中的所有数据库操作都成功,才算整个事务成功。如果事务中任何一个sql语句执行失败,那么已经执行的sql语句也必须撤销,事务状态退回到执行事务之前的状态。
  • 一致性:在事务开始之前和事务结束之后,事务的完整性约束没有被破坏。
  • 隔离性:一个事务的影响在该事务提交前对其他事物都不可见。——这通过锁来实现
  • 持久性:事务一旦提交,其结果就是永久性的。

(隔离性由锁来实现;原子性、一致性和持久性通过数据库的redo和undo来完成。)

5、不考虑事务的隔离性,会发生几种问题?

  通过锁可以实现事务隔离性的要求,使得事务可以并发地工作。因为事务隔离性的要求,锁会带来3种问题:丢失更新、脏读、不可重复读。

丢失更新:

  指一个事务正在访问修改数据,与此同时另一个事务也在访问修改此数据,两个事务互相不知道对方的存在。假如在是事务A修改数据前事务B已经修改过1次数据,那么事务A最终只能查询到假数据,丢失了更新操作。

避免措施:对两个用户读取的记录加上一个排他锁。

脏读:

一个事务读取了另一个事务未提交的数据,那这个读取就是脏读。

脏读很少发生,因为脏读发生的条件是需要隔离级别为read uncommited,而一般数据库隔离级别至少设置为read commited。

不可重复读:

  不可重复读是指在一个事务内多次读同一数据,在这个事务还没有结束时,另外一个事务也访问并修改该同一数据,那么在第一个事务的两次读数据之间,由于第二个事务的修改,第一个事务两次读到的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为不可重复读。

  如何避免:InnoDB存储引擎中,通过使用Next-Key Lock算法来避免不可重复读的问题。在Next-Key Lock算法下,对于索引的扫描,不仅仅是锁住扫描到的索引,而且还能锁住这些索引覆盖的范围。因此对于这个范围内的插入都是不允许的。InnoDB存储引擎的默认事务隔离级别是READ REPEATABLE,采用Next-Key Lock算法,就避免了不可重复读的现象。

幻读:

  是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。

如何避免:Repeatable read及以上级别通过间隙锁来防止幻读的出现,即锁定特定数据的前后间隙让数据无法被插入。

6、MySQL数据库提供的四种隔离级别?

  • read uncommitted(读未提交)
  • read committed(读已提交)
  • repeatable read(可重复读):InnoDB的默认隔离级别
  • serializable(串行)

  

7、有多少种日志?

  • 错误日志    :记录出错信息,也记录一些警告信息或者正确的信息。
  • 查询日志    :记录所有对数据库请求的信息,不论这些请求是否得到了正确的执行。
  • 慢查询日志:设置一个阈值,将运行时间超过该值的所有SQL语句都记录到慢查询的日志文件中。
  • 二进制日志:记录对数据库执行更改的所有操作。
  • 中继日志
  • 事务日志

8、事务是如何通过日志来实现的?

  • InnoDB中,事务日志通过重做(redo)日志文件和InnoDB存储引擎的日志缓冲来实现。当开始一个事务时,会记录该事务的一个LSN(日志序列号),当事务执行时,会往InnoDB的日志缓冲里插入事务日志,当事务提交时,必须将innoDB存储引擎的日志缓冲写入磁盘。也就是在写数据前,需要先写日志。这种方式称为预写日志方式

 InnoDB通过预写日志的方式来保证事务的完整性。这意味着磁盘上存储的数据页和内存缓冲池中的数据页是不同步的,对于内存缓冲池中页的修改,先是写入重做日志文件,然后再写入磁盘,因此是一种异步的方式

  • 事务有时还需要撤销,这就需要undo。对数据库进行修改时,数据库不但会产生redo,而且会产生一定量的undo,如果你执行的事务或语句由于某种原因失败了,或者如果你用一条rollback语句请求回滚,就可以利用这些undo信息将数据回滚到修改之前的样子。

9、数据库的乐观锁和悲观锁是什么?

乐观并发控制(乐观锁)和悲观并发控制(悲观锁)是并发控制主要采用的技术手段。

悲观锁:假定会发生并发冲突,屏蔽掉一切可能违反数据完整性的操作。

乐观锁:假定不会发生并发冲突,只在提交操作时检查是否违反数据完整性。

10、什么是存储过程?有哪些优缺点?

存储过程是一些预编译的SQL语句。优点是允许模块化的设计,就是说只需创建一次,以后在该程序中就可以调用多次。如果某次操作需要执行多次SQL,使用存储过程比单纯SQL语句执行要快。

  • 调用:

1)可以用一个命令对象来调用存储过程。

2)可以供外部程序调用,比如:java程序。

  • 优点: 

1)存储过程是预编译过的,执行效率高。

2)存储过程的代码直接存放于数据库中,通过存储过程名直接调用,减少网络通讯。

3)安全性高,执行存储过程需要有一定权限的用户。

4)存储过程可以重复使用,可减少数据库开发人员的工作量。

  • 缺点:移植性差

11、存储过程与触发器的区别?

  触发器的作用是在insert、delete和update命令之前或之后自动调用sql命令或者存储过程。

  触发器与存储过程非常相似,触发器也是SQL语句集,两者唯一的区别是触发器不能用EXECUTE语句调用,而是在用户执行Transact-SQL语句时自动触发(激活)执行。触发器是在一个修改了指定表中的数据时执行的存储过程。通常通过创建触发器来强制实现不同表中的逻辑相关数据的引用完整性和一致性。由于用户不能绕过触发器,所以可以用它来强制实施复杂的业务规则,以确保数据的完整性。触发器不同于存储过程,触发器主要是通过事件执行触发而被执行的,而存储过程可以通过存储过程名称名字而直接调用。当对某一表进行诸如UPDATE、INSERT、DELETE这些操作时,SQLSERVER就会自动执行触发器所定义的SQL语句,从而确保对数据的处理必须符合这些SQL语句所定义的规则。

12、索引是什么?有什么作用以及优缺点?

索引是对数据库表中一或多个列的值进行排序的结构,利用索引可快速访问数据库表的特定信息。

  举个例子:假设有一张数据表Emplyee,该表有三列:Employee_name,Employee_age,Employee_address,表中有几万条记录。现在要执行下面这条查询语句:Select * from Employee where Employee_name='Jesus'。

  如果没有数据库索引功能,数据库系统会全表扫描,逐行的遍历整张表,对于每一行都要检查其Employee_Name字段是否等于“Jesus”。而数据库索引功能索引的最大作用就是加快查询速度,它能从根本上减少需要扫表的记录/行的数量。

优点:

  • 索引加快数据库的检索速度
  • 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性;
  • 加速表和表之间的连接;
  • 使用分组和排序子句进行数据检索时,可以显著减少查询中分组和排序的时间。

缺点:

  • 创建索引和维护索引需要耗费时间,这个时间随着数据量的增加而增加;
  • 索引需要占用物理空间,不光是表需要占用数据空间,每个索引也需要占用物理空间;
  • 当对表进行增、删、改、的时候索引也要动态维护,这样就降低了数据的维护速度。

13、说一MySQL数据库几个基本的索引类型?

普通索引、唯一索引、主键索引、联合索引、全文索引

  • 唯一索引:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。
  • 主键索引:是一种特殊的唯一索引,一个表只能有一个主键,不允许有空值。 为表定义主键将自动创建主键索引。(数据库表某列或列组合,其值唯一标识表中的每一行。该列称为表的主键。)
  • 联合索引:指对表上的多个列做索引。只有在查询条件中使用了创建索引时的第一个字段,索引才会被使用。使用组合索引时遵循最左前缀集合。
  • 全文索引:主要用来查找文本中的关键字,而不是直接与索引中的值相比较。目前只有char、varchar,text 列上可以创建全文索引。

https://www.cnblogs.com/sdfgdrg/p/10095891.html

14、使用索引查询一定能提高查询的性能吗?为什么?

通常,通过索引查询数据比全表扫描要快。但是我们也必须注意到它的代价:

  索引需要空间来存储,也需要定期维护,每当有记录在表中增减或索引列被修改时,索引本身也会被修改。这意味着每条记录的INSERT、DELETE、UPDATE将为此多付出4,5 次的磁盘I/O。因为索引需要额外的存储空间和处理,那些不必要的索引反而会使查询反应时间变慢。使用索引查询不一定能提高查询性能,索引范围查询(INDEX RANGE SCAN)适用于两种情况:

  • 如果某个字段的取值范围很广,几乎没有重复,即高选择性,则此时使用B+树索引是最适合的,例如姓名。
  • 基于一个范围的检索,一般查询返回结果集小于表中记录数的20%。(MySQL数据库的优化器会预估查询可能得到的行,如果大于某一个值,则B+树会选择全表的扫描。这个值一般在20%(即当取出的数据量超过表中数据的20%,优化器就不会使用索引))

15、为数据表建立索引的原则有哪些?

  • 在最频繁使用的、用以缩小查询范围的字段上建立索引。
  • 在频繁使用的、需要排序的字段上建立索引。

16、什么情况下应不建或少建索引?

  • 对于那些在查询中很少使用或者参考的列不应该创建索引。(既然这些列很少使用到,因此有索引或者无索引并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。)
  • 对于那些只有很少数据值的列也不应该增加索引。(由于这些列的取值很少,例如人事表的性别列,在查询的结果中,结果集的数据行占了表中数据行的很大比例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加快检索速度。)
  • 对于那些定义为text, image和bit数据类型的列不应该增加索引。(这是因为,这些列的数据量要么相当大,要么取值很少。)
  • 当修改性能远远大于检索性能时,不应该创建索引。(这是因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。)

17、什么是mysql联合索引?

   联合索引是指对表上的多个列做索引。从本质上来说,联合索引还是一颗B+树,不同的是联合索引的键值的数量不是1,而是大于等于2。

  对于查询 SELECT * FROM TABLE WHERE a=xxx and b=xxx,显然可以使用(a,b)这个联合索引。对于单个的a列查询 SELECT * FROM TABLE WHERE a=xxx 也是可以使用(a,b)索引。但对于b列的查询 SELECT * FROM TABLE WHERE b=xxx 不可以使用这颗B+树索引。因为叶节点上的b值为1,2,1,4,1,2,显然不是排序的,因此对于b列的查询使用不到(a,b)的索引。

   联合索引的第二个好处是,可以对第二个键值进行排序。例如,在很多情况下我们都需要查询某个用户的购物情况,并按照时间排序,去除最近3次的购买记录,这是使用联合索引可以避免多一次的排序操作,因为索引本身在叶节点已经排序了。

  【注】:对于相同的第一个键值的数据,第二个键值是排好序的。

      对于单个列a的查询往往使用单个键的索引,因为其叶节点包含单个键值,能存放的记录更多。

18、说一说 B+树索引、哈希索引?

Hash索引和B+树索引的特点:

  • Hash索引结构的特殊性,其检索效率非常高,索引的检索可以一次定位;

  • B+树索引需要从根节点到枝节点,最后才能访问到页节点这样多次的IO访问。

为什么不都用Hash索引而使用B+树索引?

  1. Hash索引仅仅能满足"=","IN"和""查询,不能使用范围查询,因为经过相应的Hash算法处理之后的Hash值的大小关系,并不能保证和Hash运算前完全一样;

  2. Hash索引无法被用来避免数据的排序操作,因为Hash值的大小关系并不一定和Hash运算前的键值完全一样;

  3. Hash索引不能利用部分索引键查询,对于组合索引,Hash索引在计算Hash值的时候是组合索引键合并后再一起计算Hash值,而不是单独计算Hash值,所以通过组合索引的前面一个或几个索引键进行查询的时候,Hash索引也无法被利用;

  4. Hash索引在任何时候都不能避免表扫描,由于不同索引键存在相同Hash值,所以即使取满足某个Hash键值的数据的记录条数,也无法从Hash索引中直接完成查询,还是要回表查询数据;

  5. Hash索引遇到大量Hash值相等的情况后性能并不一定就会比B+树索引高。

19、B树和B+树的区别?

B+树是一种平衡查找树在B+树中,所有记录节点都是按键值的大小顺序存放在同一层的叶节点中,各叶结点指针进行连接。

(平衡二叉树AVL:首先符合二叉查找树的定义(最结点的值比根节点小,右结点的值比根结点大),其次必须满足任何节点的左右两个子树的高度最大差为1。)

  • B树  :每个节点都存储key和data,所有节点组成这棵树,并且叶子节点指针为nul,叶子结点不包含任何关键字信息
  • B+树:所有的叶子结点中包含了全部关键字的信息,及指向含有这些关键字记录的指针,且叶子结点本身依关键字的大小自小而大的顺序链接,所有的非终端结点可以看成是索引部分。

20、为什么说B+比B树更适合实际应用中操作系统的文件索引和数据库索引?

(1)B+的磁盘读写代价更低

  B+的内部结点并没有指向关键字具体信息的指针。因此其内部结点相对B树更小。如果把所有同一内部结点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多。一次性读入内存中的需要查找的关键字也就越多。相对来说IO读写次数也就降低了。

(2)B+tree的查询效率更加稳定

  由于非终结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。

21、聚集索引和非聚集索引区别?

  数据库中的B+索引可以分为聚集索引和辅助聚集索引。不管是聚集索引还是非聚集的索引,其内部都是B+树的,即高度平衡的,叶节点存放着所有的数据,聚集索引与非聚集索引不同的是,叶节点存放的是否是一整行的信息

  • 聚集索引(clustered index):

  聚集索引就是按照每张表的主键构造一颗B+树并且叶节点中存放着整张表的行记录数据,因此也让聚集索引的叶节点成为数据页。聚集索引的这个特性决定了索引组织表中数据也是索引的一部分。由于实际的数据页只能按照一颗B+树进行排序,因此每张表只能拥有一个聚集索引

  聚集索引表记录的排列顺序和索引的排列顺序一致,所以查询效率快,只要找到第一个索引值记录,其余就连续性的记录在物理也一样连续存放。聚集索引对应的缺点就是修改慢,因为为了保证表中记录的物理和索引顺序一致,在记录插入的时候,会对数据页重新排序。

  • 非聚集索引(nonclustered index)(也叫辅助索引):

  对于辅助索引(非聚集索引),叶级别不包含行的全部数据。聚集索引键来告诉InnoDB存储引擎,哪里可以找到与索引相对应的行数据。辅助索引的存在并不影响数据在聚集索引中的组织,因此每张表上可以有多个辅助索引通过辅助索引来寻找数据时,InnoDB存储引擎会遍历辅助索引并通过叶级别的指针获得指向主键索引的主键,然后再通过主键索引来找到一个完整的行记录

  非聚集索引指定了表中记录的逻辑顺序,但是记录的物理和索引不一定一致,两种索引都采用B+树结构,非聚集索引的叶子层并不和实际数据页相重叠,而采用叶子层包含一个指向表中的记录在数据页中的指针方式。非聚集索引层次多,不会造成数据重排。

根本区别:

聚集索引和非聚集索引的根本区别是表记录的排列顺序和与索引的排列顺序是否一致。

22、说一说drop、deletetruncate的区别?

  • drop直接删掉表。
  • truncate删除表中数据,再插入时自增长id又从1开始。
  • delete删除表中数据,可以加where字句。

(1)truncate和delete只删除数据,而drop则删除整个表(结构和数据)。

(2)delete语句执行删除的过程是每次从表中删除一行,并且同时将该行的删除操作作为事务记录在日志中保存以便进行进行回滚操作。truncate table则一次性地从表中删除所有的数据并不把单独的删除操作记录记入日志保存,删除行是不能恢复的。并且在删除的过程中不会激活与表有关的删除触发器。执行速度快。

(3)执行速度:drop> truncate >delete

(4)delete语句是dml,这个操作会放到rollback segement,事务提交之后才生效。如果有相应的trigger(触发器),执行的时候将被触发truncate;

    dropddl,操作立即生效,原数据不放到rollback segment,不能回滚,操作不触发trigger

(5)应用范围:truncate只能对table;delete可以是table和view

23、drop、deletetruncate分别在什么场景之下使用?

  • 不再需要一张表的时候,用drop
  • 想删除部分数据行时候,用delete,并且带上where子句
  • 保留表而删除所有数据的时候用truncate

24、超键、候选键、主键、外键分别是什么?

 超键   :在关系中能唯一标识元组的属性集称为关系模式的超键。一个属性可以为作为一个超键,多个属性组合在一起也可以作为一个超键。超键包含候选键和主键。

候选键:是最小超键,即没有冗余元素的超键。

主键    :数据库表中对存储数据对象予以唯一和完整标识的数据列或属性的组合。一个数据列只能有一个主键,且主键的取值不能缺失,即不能为空值(Null)。

外键    :在一个表中存在的另一个表的主键称此表的外键。

25、mysql为什么建议用自增列作为主键?

  如果我们定义了主键(PRIMARY KEY),那么InnoDB会选择主键作为聚集索引、如果没有显式定义主键,则InnoDB会选择第一个不包含有NULL值的唯一索引作为主键索引、如果也没有这样的唯一索引,则InnoDB会选择内置6字节长的ROWID作为隐含的聚集索引(ROWID随着行记录的写入而主键递增,这个ROWID不像ORACLE的ROWID那样可引用,是隐含的)。

  1. 使用自增列(INT/BIGINT类型)做主键,这时候写入顺序是自增的,和B+数叶子节点分裂顺序一致;
  2. 该表不指定自增列做主键,同时也没有可以被选为主键的唯一索引(上面的条件),这时候InnoDB会选择内置的ROWID作为主键,写入顺序和ROWID增长顺序一致;
  3. 除此以外,如果一个InnoDB表又没有显示主键,又有可以被选择为主键的唯一索引,但该唯一索引可能不是递增关系时(例如字符串、UUID、多字段联合唯一索引的情况),该表的存取效率就会比较差。

26、MySQL中的varchar和char的区别以及varchar(50)中的50代表的涵义?

  char是一种固定长度的类型,varchar是一种可变长度的类型。

varchar(50)中50的含义:
    最多存放50个字符,varchar(50)和(200)存储hello所占空间一样,但后者在排序时会消耗更多内存,因为order by col采用fixed_length计算col长度。ppp-

int(20)中20的含义:

   是指显示字符的长度
   但要加参数的,最大为255,比如它是记录行数的id,插入10笔资料,它就显示00000000001 ~~~00000000010,当字符的位数超过11,它也只显示11位,如果你没有加那个让它未满11位就前面加0的参数,它不会在前面加0.
  20表示最大显示宽度为20,但仍占4字节存储,存储范围不变;

mysql为什么这么设计:
   对大多数应用没有意义,只是规定一些工具用来显示字符的个数;int(1)和int(20)存储和计算均一样。

27、什么是视图?视图的使用场景有哪些?

   视图(View)是一个命名的虚表,它由一个查询来定义,可以当作表使用。

视图有什么用(应用场景)

1、当一个查询你需要频频的作为子查询使用时,视图可以简化代码,直接调用而不是每次都去重复写这个东西。
2、系统的数据库管理员,需要给他人提供一张表的某两列数据,而不希望他可以看到其他任何数据,这时可以建一个只有这两列数据的视图,然后把视图公布给他。

视图与表的区别

      1、视图是已经编译好的sql语句,而表不是。
      2、视图没有实际的物理记录,而表有。
      3、表是内容,视图是窗口。
      4、表只用物理空间而视图不占用物理空间,视图只是逻辑概念的存在,表可以及时对它进行修改,但视图只能由创建的语句来修改。
      5、视图是查看数据表的一种方法,可以查询数据表中某些字段构成的数据,只是一些SQL语句的集合。从安全的角度说,视图可以不给用户接触数据表,从而不知道表结构。
      6、表属于全局模式中的表,是实表;视图属于局部模式的表,是虚表。 
      7、视图的建立和删除只影响视图本身,不影响对应的基本表。
      8、不能对视图进行update或者insert into操作。

28、数据库三大范式?

第一范式(1NF)
  (在任何一个关系数据库中,第一范式(1NF)是对关系模式的基本要求,不满足第一范式(1NF)的数据库就不是关系数据库。)

  所谓第一范式(1NF)是指数据库表的每一列都是不可分割的基本数据项第一范式就是无重复的列。强调的是列的原子性,即列不能够再分成其他几列。

第二范式(2NF)
  满足第二范式(2NF)必须先满足第一范式(1NF)。另外包含两部分内容,一是表必须有主键;二是没有包含在主键中的列必须完全依赖于主键,而不能只依赖于主键的一部分。

第三范式(3NF)
  满足第三范式(3NF)必须先满足第二范式(2NF)第三范式就是属性不依赖于其它非主属性。非主键列必须直接依赖于主键,不能存在传递依赖

29、sql优化

 1. explain sql 分析sql语句,这个语句可以打印出的各种item的意义:

  • select_type :表示查询中每个select子句的类型
  • type :表示MySQL在表中找到所需行的方式,又称“访问类型”
  • possible_keys :指出MySQL能使用哪个索引在表中找到行,查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询使用。
  • key :显示MySQL在查询中实际使用的索引,若没有使用索引,显示为NULL。
  • key_len :表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度
  • ref :表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值 
  • Extra :包含不适合在其他列中显示但十分重要的额外信息

2. 查询语句不同元素(where、jion、limit、group by、having等等)执行先后顺序?

查询中用到的关键词主要包含6个,并且他们的顺序依次为 select--from--where--group by--having--order by。

其中select和from是必须的,其他关键词是可选的。

30、非关系型数据库和关系型数据库区别,优势比较?

非关系型数据库的优势:

  • 性能:NOSQL是基于键值对的,可以想象成表中的主键和值的对应关系,而且不需要经过SQL层的解析,所以性能非常高。
  • 可扩展性:同样也是因为基于键值对,数据之间没有耦合性,所以非常容易水平扩展。

关系型数据库的优势:

  • 复杂查询:可以用SQL语句方便的在一个表以及多个表之间做非常复杂的数据查询。
  • 事务支持:使得对于安全性能很高的数据访问要求得以实现。

其他:

1.对于这两类数据库,对方的优势就是自己的弱势,反之亦然。

2.NOSQL数据库慢慢开始具备SQL数据库的一些复杂查询功能,比如MongoDB。

3.对于事务的支持也可以用一些系统级的原子操作来实现例如乐观锁之类的方法来曲线救国,比如Redis set nx。

31、什么是 内连接、外连接、交叉连接、笛卡尔积等?

  • 内连接: 只连接匹配的行
  • 左外连接: 包含左边表的全部行(不管右边的表中是否存在与它们匹配的行),以及右边表中全部匹配的行
  • 右外连接: 包含右边表的全部行(不管左边的表中是否存在与它们匹配的行),以及左边表中全部匹配的行

例如1:
SELECT a.,b. FROM luntan LEFT JOIN usertable as b ON a.username=b.username

例如2:
SELECT a.,b. FROM city as a FULL OUTER JOIN user as b ON a.username=b.username

  • 全外连接: 包含左、右两个表的全部行,不管另外一边的表中是否存在与它们匹配的行。
  • 交叉连接: 生成笛卡尔积-它不使用任何匹配或者选取条件,而是直接将一个数据源中的每个行与另一个数据源的每个行都一一匹配

例如:
SELECT type,pub_name FROM titles CROSS JOIN publishers ORDER BY type

1.以A,B两张表为例
A left join B
选出A的所有记录,B表中没有的以null 代替
right join 同理

2.inner join
A,B的所有记录都选出,没有的记录以null代替

3.cross join (笛卡尔积)
A中的每一条记录和B中的每一条记录生成一条记录
例如A中有4条,B中有4条,cross join 就有16条记录

32、SQL语言分类

  • 数据查询语言DQL :基本结构是由SELECT子句、FROM子句、WHERE子句组成的查询块。
  • 数据操纵语言DML :1)插入INSERT 2) 更新:UPDATE 3) 删除:DELETE
  • 数据定义语言DDL :用来创建数据库中的各种对象-----表、视图、索引、同义词、聚簇等如:CREATE TABLE/VIEW/INDEX/SYN/CLUSTER
          • DDL操作是隐性提交的!不能rollback
  • 数据控制语言DCL :用来授予或回收访问数据库的某种特权,并控制数据库操纵事务发生的时间及效果,对数据库实行监视等。ROLLBACK/COMMIT
  • (1) 显式提交
    • 用COMMIT命令直接完成的提交为显式提交。其格式为:SQL>COMMIT;
  • (2) 隐式提交
    • 用SQL命令间接完成的提交为隐式提交。这些命令是:ALTER,AUDIT,COMMENT,CONNECT,CREATE,DISCONNECT,DROP,EXIT,GRANT,NOAUDIT,QUIT,REVOKE,RENAME。
  • (3) 自动提交
    • 若把AUTOCOMMIT设置为ON,则在插入、修改、删除语句执行后,系统将自动进行提交。其格式为:SQL>SET AUTOCOMMIT ON;

33、like %和-的区别

  % 通配符:表示任何字符出现任意次数 (可以是0次)。
  _ 通配符:表示只能匹配单个字符,不能多也不能少,就是一个字符。

使用通配符进行模糊查询需要用 like操作符,例:

  SELECT * FROM products WHERE products.prod_name like '%es%';

  SELECT * FROM products WHERE products.prod_name like '_es';

【注】如果在使用like操作符时,后面的没有使用通用匹配符效果是和 = 是一致的。

   SELECT * FROM products WHERE products.prod_name like '1000':只能匹配的结果为1000,而不能匹配像JetPack 1000这样的结果。

34、count(*)、count(1)、count(column)的区别

  • count(*)  :对行的数目进行计数,包含NULL
  • count(column) :对特定的列的值具有的行进行计数,不包含NULL值。

  • count(1)这个用法和count(*)的结果是一样的。

性能问题:

  1. 任何情况下SELECT COUNT(*) FROM tablename是最优选择;
  2. 尽量减少SELECT COUNT(*) FROM tablename WHERE COL = ‘value’ 这种查询;
  3. 杜绝SELECT COUNT(COL) FROM tablename WHERE COL2 = ‘value’ 的出现。
  • 如果表没有主键,那么count(1)比count(*)快。
  • 如果有主键,那么count(主键,联合主键)比count(*)快。
  • 如果表只有一个字段,count(*)最快。

  count(1)跟count(主键)一样,只扫描主键;count(*)跟count(非主键)一样,扫描整个表。明显前者更快一些。

35、你们数据库是否支持emoji表情,如果不支持,如何操作?

如果是utf8字符集的话,需要升级至utf8_mb4方可支持。

36、你是如何监控你们的数据库的?你们的慢日志都是怎么查询的?

监控的工具有很多,例如zabbix,lepus,我这里用的是lepus。

  • slow_query_log        :慢查询开启状态。
  • slow_query_log_file :慢查询日志存放的位置(这个目录需要MySQL的运行帐号的可写权限,一般设置为MySQL的数据存放目录)。
  • long_query_time      :查询超过多少秒才记录。

 开启慢日志查询:set global slow_query_log='ON';

那么开启了慢查询日志后,什么样的SQL才会记录到慢查询日志里面呢? 

  这个是由参数long_query_time控制,默认情况下long_query_time的值为10秒,可以使用命令修改,也可以在my.cnf参数里面修改。运行时间大于long_query_time(非大于等于),才会记录到慢查询日志里。

参考史上最全的数据库面试题,不看绝对后悔

  【MySQL】20个经典面试题

  数据库常见面试题(附答案)

猜你喜欢

转载自www.cnblogs.com/toria/p/11204226.html