面试数据库

面试篇-数据库

2018-07-20  本文已影响346人  terry蒋

本问很多内容摘录和参考自下面的文章,感谢他们的共享:

面经整理-Java基础 https://blog.csdn.net/u012294820/article/details/78732771

数据库分类

sql
1)mysql
2)sqlserver

nosql
1)键值对数据库:redis、memcache
2)列存储数据库:hbase
3)文档型数据库:mongdb
4)图形数据库:graph

查询优化

性能优化:

解决方案:

索引

索引概念:
索引是对数据库表中一个或多个列的值进行排序的结构

索引的原理:
数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中数据。索引的实现通常使用B树及其变种B+树。
在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法。这种数据结构,就是索引。

优点:
1.大大加快检索速度;
2.创建唯一性索引,保证数据库表中每一行数据的唯一性;
3.加速表和表之间的连接;
4.在使用分组和排序子句进行数据检索时,可以显著减少查询中分组和排序的时间:
(1)大大减少服务器需要扫描的数据量
(2)帮助服务器避免排序和临时表
(3)将所及I/O变为顺序I/O

缺点:
1.索引需要占用数据表以外的物理存储空间
2.创建索引和维护索引要花费一定的时间
3.当对表进行更新操作时,索引需要被重建,这样降低了数据的维护速度。

使用原则:

  1. 不要索引数据量不大的表,对于小表来讲,表扫描的成本并不高。
  2. 不要设置过多的索引,在没有聚集索引的表中,最大可以设置249个非聚集索引,过多的索引首先会带来更大的磁盘空间,而且在数据发生修改时,对索引的维护是特别消耗性能的。所以:一般一张表建立最多5个索引
  3. 合理应用复合索引,有某些情况下可以考虑创建包含所有输出列的复合索引。
  4. 对经常使用范围查询的字段,可能考虑聚集索引。
  5. 避免对不常用的列,逻辑性列,大字段列创建索引。

导致sql不走索引的情况:

  1. 在where查询条件后面带有(+、-、*、/、!、<>、%)操作符将会导致查询不走索引而而选择全表查询
  2. 在where子句中判断is null,或not in ,not exist
  3. where子句后面用or链接,但是一个字段有索引而另外的字段没有索引就会导致不走索引
  4. 使用like时如果前面有%也会导致sql不走索引比如
    SELECT * FROM TB_NAME WHERE uname LIKE'ABC%' -- 走索引
    SELECT * FROM houdunwang WHERE uname LIKE "%ABC%" -- 不走索引
  5. 对索引列进行函数计算也会导致sql不走索引比如
    SELECT TB_NAME FROM stu WHERE age+10=30;
  6. 建立组合索引,但查询谓词并未使用组合索引的第一列。
  7. where子句中使用参数,select id from t where num=@num
  8. 类型错误,字段类型为varchar,where条件用number

参考一:Mysql引起索引失效的原因总结
参考二:造成数据库索引失效的几种原因

索引类型:

普通索引:create index stusno on student(sno),alter table
唯一索引: UNIQUE 例如:create unique index stusno on student(sno);
表明此索引的每一个索引值只对应唯一的数据记录,对于单列惟一性索引,这保证单列不包含重复的值。对于多列惟一性索引,保证多个值的组合不重复。

主键索引: primary key
数据库表经常有一列或多列组合,其值唯一标识表中的每一行。该列称为表的主键。在数据库关系图中为表定义主键将自动创建主键索引,主键索引是唯一索引的特定类型。该索引要求主键中的每个值都唯一。当在查询中使用主键索引时,它还允许对数据的快速访问。

聚集索引:cluster
在聚集索引中,表中行的物理顺序与键值的逻辑(索引)顺序相同。一个表只能包含一个聚集索引。 如果某索引不是聚集索引,则表中行的物理顺序与键值的逻辑顺序不匹配。与非聚集索引相比,聚集索引通常提供更快的数据访问速度。

全文索引:fulltext

举例:
CREATE INDEX indextest5 ON textbook (tag5)
ALTER TABLE textbook ADD PRIMARY KEY (timeKey)
ALTER TABLE textbook ADD UNIQUE indextest0 (timeKey)
ALTER TABLE textbook ADD INDEX indextest3 (tag3)
ALTER TABLE textbook ADD FULLTEXT indextest4 (tag4)
ALTER TABLE textbook ADD CLUSTERED indextest6 (tag6)

实现方式

  1. B+树
    我们经常听到B+树就是这个概念,用这个树的目的和红黑树差不多,也是为了尽量保持树的平衡,当然红黑树是二叉树,但B+树就不是二叉树了,节点下面可以有多个子节点,数据库开发商会设置子节点数的一个最大值,这个值不会太小,所以B+树一般来说比较矮胖,而红黑树就比较瘦高了。
    关于B+树的插入,删除,会涉及到一些算法以保持树的平衡,这里就不详述了。ORACLE的默认索引就是这种结构的。
    如果经常需要同时对两个字段进行AND查询,那么使用两个单独索引不如建立一个复合索引,因为两个单独索引通常数据库只能使用其中一个,而使用复合索引因为索引本身就对应到两个字段上的,效率会有很大提高。

  2. 散列索引
    第二种索引叫做散列索引,就是通过散列函数来定位的一种索引,不过很少有单独使用散列索引的,反而是散列文件组织用的比较多。
    散列文件组织就是根据一个键通过散列计算把对应的记录都放到同一个槽中,这样的话相同的键值对应的记录就一定是放在同一个文件里了,也就减少了文件读取的次数,提高了效率。
    散列索引呢就是根据对应键的散列码来找到最终的索引项的技术,其实和B树就差不多了,也就是一种索引之上的二级辅助索引,我理解散列索引都是二级或更高级的稀疏索引,否则桶就太多了,效率也不会很高。

  3. 位图索引
    位图索引是一种针对多个字段的简单查询设计的一种特殊的索引,适用范围比较小,只适用于字段值固定并且值的种类很少的情况,比如性别,只能有男和女,或者级别,状态等等,并且只有在同时对多个这样的字段查询时才能体现出位图的优势。
    位图的基本思想就是对每一个条件都用0或者1来表示,如有5条记录,性别分别是男,女,男,男,女,那么如果使用位图索引就会建立两个位图,对应男的10110和对应女的01001,这样做有什么好处呢,就是如果同时对多个这种类型的字段进行and或or查询时,可以使用按位与和按位或来直接得到结果了。MySQL不支持

三种索引实现方式的比较

B+树的基本原理?

MySQL是怎么用B+树?

索引的数据结构?

使用索引查询一定能提高查询的性能吗?
通常,通过索引查询数据比全表扫描要快.但是我们也必须注意到它的代价:

聚簇索引是怎么存在B+树里面的?

聚簇索引索引和非聚簇索引的区别

聚簇索引:
索引顺序与表中记录的物理顺序一致
非聚簇索引:
索引顺序与表中记录的物理顺序无关

参考:聚簇索引与非聚簇索引的区别

复合索引
Mysql从左到右的使用索引中的字段,一个查询可以只使用索引中的一部份,但只能是最左侧部分。例如索引是key index (a,b,c)。 可以支持a | a,b| a,b,c 3种组合进行查找,但不支持 b,c进行查找 ,当最左侧字段是常量引用时,索引就十分有效。

有三种查询,1)字段A查询,2)字段B查询,3)字段A和字段B复合查询,至少需要建立几个索引。
三种查询对应的索引:idx_A,idx_B,idx_A_B

至少2个索引,如果是按照AB顺序的复合查询,那么需要idx_B和idx_A_B索引。因为复合idx_A_B只支持A或者AB,不支持B查询
参考一:mysql数据库复合索引

MySQL查询记录时,每次只使用一个索引

原因:

强制使用指定的索引:
如果有多个索引,MySQL会自己选择使用其中一个,当然,我们自己也可以强制让它使用某一个索引(select * from table force index(ziduan1_index) limit 2;(强制使用索引"ziduan1_index"))。
参考一:数据库中查询记录时是否每次只能使用一个索引?

100个字段都是经常查询的,如何建索引?是对这100个字段,分别建立索引?还是对这100个字段,建立复合索引

分析:

事务(ACID)

含义:

作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行

原则:

原子性(Atomicity):一个事务(Transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。

一致性(Consistency): 在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的默认规则,这包含资料的精准度、串联新以及后续数据库可以自发性地完成预定的工作。A转账给B,执行事务之前:A+B=100,执行事务之后:A+B=100

隔离性(Isolation): 当两个或者多个事务并发访问(此处访问指查询和修改的操作)数据库的同一数据时所表现出的互相关系。事务隔离分为不同的级别,包括读不提交(Read uncommitted)、读提交(Read committed)、可重复读(Repeatable read)和串行化(Serializable)。多个事务并发访问相互之间不影响,A事务的结果不会覆盖B事务的结果

持久性(Durability): 在事务完成以后,该事务对数据库所作的更改便持久地保存在数据库之中,而且是完全的。事务一旦提交,对数据库数据的改变就是永久性的

由于一项操作通常会包含许多子操作,而这些子操作可能会因为硬件的损坏或其他因素产生问题,要正确实现ACID并不容易。ACID建议数据库将所有需要更新以及修改的资料一次操作完毕,但实际上并不可行。

目前主要有两种方式实现ACID:

第一种是Write ahead logging,也就是日志式的方式。
第二种是Shadow paging。

Write ahead logging(预写日志):

  1. 事务所引起的所有改动都要记录在日志中,在事务提交完成之前,所有的这些记录必须被写入硬盘;
  2. 一个数据库的缓冲页直到被记入日志后才能发生修改。直到缓冲页对应的日志被写入硬盘后,该缓冲页才会存入硬盘;
  3. 当缓冲页被修改和日志被更新修改时,必须加上互斥锁,以保证改动被记录到日志中的顺序与它发生的顺序是一致的。

以上规则的结果:
如果一条日志记录未被存入硬盘,则它可以被忽略,因为该日志中包含的改动一定属于未提交的事务。此外,这样的日志不能反映已持久化在数据库中的改动;
日志记录按顺序记录系统的改动。加锁协议(latch protocol)保证如果有对于同一页改动的两条日志记录,则两条记录的顺序反映对页发生改变的顺序。

事务隔离级别

不考虑隔离性,会引发一下问题:

关系型数据库的范式

第一范式: 每个属性不可再分
第二范式: 消除部分依赖,满足第一范式,表中的非主属性必须完全依赖于主键(全部主属性)
第三范式: 消除传递依赖,满足第二范式,非主属性必须互不依赖

视图

视图是一种虚拟的表,具有和物理表相同的功能。可以对视图进行增,改,查,操作,试图通常是有一个表或者多个表的行或列的子集。对视图的修改不影响基本表。它使得我们获取数据更容易,相比多表查询。

只暴露部分字段给访问者,所以就建一个虚表,就是视图。

查询的数据来源于不同的表,而查询者希望以统一的方式查询,这样也可以建立一个视图,把多个表查询结果联合起来,查询者只需要直接从视图中获取数据,不必考虑数据来源于不同表所带来的差异

SQL

从表TABLE_NAME中提取10条记录
sql server:
select top 10 * from TABLE_NAME;

-- mysql:
select * from TABLE_NAME limit 10;

drop、delete与truncate的区别

SQL中的drop、delete、truncate都表示删除,但是三者有一些差别:

drop、delete与truncate分别在什么场景之下使用?

SQL 约束有哪几种?

sql注入,如何避免

主键、外键、候选键、超键

MySQL的常用引擎

MySQL数据库中,常用的引擎主要就是2个:Innodb和MyIASM。这篇文章将主要介绍这两个引擎,以及该如何去选择引擎,最后在提一下这2种引擎所使用的数据结构是什么。

Innodb引擎。

Innodb引擎提供了对数据库ACID事务的支持。并且还提供了行级锁和外键的约束。它的设计的目标就是处理大数据容量的数据库系统。它本身实际上是基于Mysql后台的完整的系统。Mysql运行的时候,Innodb会在内存中建立缓冲池,用于缓冲数据和索引。但是,该引擎是不支持全文搜索的。同时,启动也比较的慢,它是不会保存表的行数的。当进行Select count(*) from table指令的时候,需要进行扫描全表。
所以当需要使用数据库的事务时,该引擎就是首选。由于锁的粒度小,写操作是不会锁定全表的。所以在并发度较高的场景下使用会提升效率的。

MyIASM引擎

mysql5.5之前,它是MySql的默认引擎,5.5开始默认引擎是Innodb,但不提供事务的支持,也不支持行级锁和外键。因此当执行Insert插入和Update更新语句时,即执行写操作的时候需要锁定这个表。所以会导致效率会降低。不过和Innodb不同的是,MyIASM引擎是保存了表的行数,于是当进行Select count(*) from table语句时,可以直接的读取已经保存的值而不需要进行扫描全表。

所以,如果表的读操作远远多于写操作时,并且不需要事务的支持的。可以将MyIASM作为数据库引擎的首先。

这两种引擎的选择。其实上面已经提到了。这里我在补充了两点:

  1. 大容量的数据集时趋向于选择Innodb。因为它支持事务处理和故障的恢复。Innodb可以利用数据日志来进行数据的恢复。主键的查询在Innodb也是比较快的。
  2. 大批量的插入语句时(这里是INSERT语句)在MyIASM引擎中执行的比较的快,但是UPDATE语句在Innodb下执行的会比较的快,尤其是在并发量大的时候。

两种引擎所使用的索引的数据结构是什么?

答案是都是B+树。

mysql一般用的什么数据库引擎

mysql5.5以后默认的是InnoDB存储引擎

InnoDB和MyISAM之间的区别、应用场景

区别:
  1. MyISAM不支持事务,InnoDB是事务类型的存储引擎
  2. MyISAM只支持表级锁,BDB支持页级锁和表级锁默认为页级锁,而InnoDB支持行级锁和表级锁默认为行级锁
  3. MyISAM引擎不支持外键,InnoDB支持外键
  4. MyISAM引擎的表在大量高并发的读写下会经常出现表损坏的情况
  5. 对于count()查询来说MyISAM更有优势
  6. InnoDB是为处理巨大数据量时的最大性能设计,它的CPU效率可能是任何其它基于磁盘的关系数据库引擎所不能匹敌的
  7. MyISAM支持全文索引(FULLTEXT),InnoDB不支持
  8. MyISAM引擎的表的查询、更新、插入的效率要比InnoDB高
应用场景:

MyISAM:(1)做很多count 的计算;(2)插入不频繁,查询非常频繁;(3)没有事务。
InnoDB:(1)可靠性要求比较高,或者要求事务;(2)表更新和查询都相当的频繁,并且行锁定的机会比较大的情况。

数据库连接

通过JDBC访问数据库包含下面哪几步?

  1. 加载JDBC驱动程序
  2. 提供JDBC连接的URL
  3. 创建数据库的连接
  4. 创建一个Statement
  5. 执行SQL语句
  6. 处理结果
  7. 关闭JDBC对象

存储过程

触发器的作用

触发器是一种特殊的存储过程,主要是通过事件来触发而被执行的。它可以强化约束,来维护数据的完整性和一致性,可以跟踪数据库内的操作从而不允许未经许可的更新和变化。可以联级运算。如,某表上的触发器上包含对另一个表的数据操作,而该操作又会导致该表触发器被触发。

数据库的乐观锁和悲观锁

数据库管理系统(DBMS)中的并发控制的任务是确保在多个事务同时存取数据库中同一数据时不破坏事务的隔离性和统一性以及数据库的统一性。

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

悲观锁和乐观锁的区别以及应用场景

区别:

应用场景: 读取频繁使用乐观锁,写入频繁使用悲观锁。

MySQL分表、分区、分库

连表查询:笛卡尔积通过什么连接得到sql

select * from a, b

inner join,left join,right join的区别

Table A TableB

aid adate bid bdate

1 a1 1 b1

2 a2 2 b2

3 a3 4 b4

select * from a inner join b on a.aid = b.bid

仅取出匹配的数据,结果:

1 a1 b1

2 a2 b2

select * from a left join b on a.aid = b.bid

首先取出a表中所有数据,然后再加上与a,b匹配的的数据,结果::

1 a1 b1

2 a2 b2

3 a3 空字符

select * from a right join b on a.aid = b.bid

指的是首先取出b表中所有数据,然后再加上与a,b匹配的的数据,结果:

1 a1 b1

2 a2 b2

4 空字符 b4

有全字段重复数据怎么去重,写sql语句:

delete from vitae a

where (a.peopleId,a.seq) in (select peopleId,seq from vitae group by peopleId,seq having count(*) > 1)

and rowid not in (select min(rowid) from vitae group by peopleId,seq having count(*)>1)

数据库中某个表查询和存取数据量很大时怎么处理

数据库设计:

SQL语句:

Java代码:

参考一:在一个千万级的数据库查寻中,如何提高查询效率?

做项目时怎么设计数据库,怎么决定主键

因为我自己谈到用过redis,所以又问了我redis的原理和优势

数据库的底层设计,文件如何存储,数据如何查询

MongoDB和MySQL的区别

MongoDB:日志

存储方式:虚拟内存+持久化。

查询语句:是独特的Mongodb的查询方式。

适合场景:事件的记录,内容管理或者博客平台等等。

架构特点:可以通过副本集,以及分片来实现高可用。

数据处理:数据是存储在硬盘上的,只不过需要经常读取的数据会被加载到内存中,将数据存储在物理内存中,从而达到高速读写。

不支持事务

参考一:数据库-面试题(持续更新)

参考二:http://www.cnblogs.com/remember-forget/p/6140112.html

参考三:mysql数据库面试总结

参考四:数据库面试宝典

参考五:SQL经典面试题及答案

参考六:SQL经典面试题目总结

参考七:15个 MySQL 基础面试题,DBA 们准备好了吗?

参考八:MySQL索引使用方法和性能优化

参考九:和刚入门的菜鸟们聊聊--什么是聚簇索引与非聚簇索引

上一篇下一篇

猜你喜欢

热点阅读