MYSQL数据库面经

数据库面试题

1 Mysql的事务

Mysql事务主要用于处理操作量大,复杂度高的数据。比如说,在人员管理系统中,你删除一个人员,你既需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等等,这样,这些数据库操作语句就构成一个事务;

1.1事务的基本要素(ACID)

● 原子性(Atomicity):原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
● 一致性(Consistency):事务必须使数据库从一个一致性状态变换到另外一个一致性状态。
● 隔离性(Isolation) :事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
● 持久性(Durability):持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响。

事务的并发问题:
● 脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据;
● 不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果不一致;
● 幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。

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

1.2事务的ACID原理是怎么实现的?

事务是基于重做日志文件(redo log)和回滚日志(undo log)实现的;
① 每提交一个事务必须先将该事务的所有日志写入到redo log文件中进行持久化,数据库就可以通过redo log来保证事务的原子性和持久性;
② 每当有修改事务时,还会产生undo log,如果需要回滚,则根据undo log的反向语句进行逻辑操作,比如insert一条记录就delete一条记录。undo log主要实现数据库的一致性;

undo log:当进行数据修改时还会记录undo log,undo log用于数据的撤回操作,它保留了记录修改前的内容。通过undo log可以实现事务回滚,并且可以根据undo log回溯到某个特定的版本的数据,实现MVCC;

redo log:叫重做日志(redo log)是InnoDB引擎级别,用来记录InnoDB存储引擎的事务日志,不管事务是否提交都会记录下来,用于数据恢复。当数据库发生故障,InnoDB存储引擎会使用redo log恢复到发生故障前的时刻,以此来保证数据的完整性。将参数innodb_flush_log_at_tx_commit设置为1,那么在执行commit时会将redo log同步写到磁盘;

1.3 Mysql事务的隔离级别

为什么需要事务的隔离级别?
事务的隔离级别,就是为了解决上面几种问题而诞生的,为什么要有事务的隔离级别,因为事务的隔离级别越高,在并发下会产生的问题就越少,但同时付出的性能消耗也将越大,因此很多时候必须在并发性和性能之间做一个权衡。所以设立了几种事务的隔离级别,以便让不同的项目可以根据自己项目的并发情况选择合适的事务隔离级别,对于在事务隔离级别之外会产生的并发问题,在代码中做补偿。

MYSQL数据库面经_第1张图片
是:表示会出现脏读、不可重复读、幻读;
否:表示不会出现上述事务并发问题;

4种事务隔离级别:
(1)读未提交:一个事务还没提交时,它做的变更就能被别的事务看到;
(2)读已提交:一个事务提交之后,它做的变更才会被其它事务看到;
(3)可重复读:一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。当然,在可重复读隔离级别下,未提交变更对其它事务也是不可见的;
(4)串行化:对于同一行记录,读写都会加锁,当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成才能继续执行;

1.4 Mysql(InnoDB)是如何实现事务隔离的?

主要是通过2种方式进行实现的:①锁机制 ②MVCC机制,提交读和可重复读可以通过MVCC实现,串行化可以通过锁机制实现;

(1)读未提交,它是性能最好,也可以说它是最野蛮的方式,因为它压根儿就不加锁,所以根本谈不上什么隔离效果,可以理解为没有隔离;
(2)串行化,读的时候加共享锁(读锁),也就是其他事务可以并发读,但是不能写。写的时候加排它锁(写锁),其他事务不能并发写也不能并发读;
(3)可重复读:为了解决不可重复读,或者为了实现可重复读,Mysql采用了 MVCC (多版本并发控制) 的方式,利用MVCC实现一致性非锁定读,这就有保证在同一个事务中多次读取相同的数据返回的结果是一样的,解决了不可重复读的问题;
(4)解决幻读问题:利用Gap Locks(间隙锁)和Next-Key可以阻止其它事务在锁定区间内插入数据,因此解决了幻读问题;

Record Locks(记录锁):在索引记录上加锁;
Gap Locks(间隙锁):在索引记录之间加锁,或者在第一个索引记录之前加锁,或者在最后一个索引记录之后加锁;
Next-Key Locks:在索引记录上加锁,并且在索引记录之前的间隙加锁。它相当于是Record Locks与Gap Locks的一个结合;

MVCC(作用:提高并发读写的性能,不用加锁就能让多个事务并发读写):
MVCC(Multi-Version-Concurrent-Control)全称是“多版本并发控制”,是一种控制并发的方法,主要用来提高数据库的并发性能,其基本思想是为每次事务生成一个新版本数据,在读数据时选择不同版本的数据即可实现对事务结果的完整性读取;

MVCC实现的大致原理(针对InnoDB引擎):
数据库表中的每一行数据都有一个隐藏的回滚指针,用于指向该行修改前的最后一个历史版本,这个历史版本存放在undo log日志中。如果要执行更新操作,会将原记录放入到undo log日志中,并通过隐藏的回滚指针指向undo log中的原记录。如果其它事务此时需要查询时,就是查询undo log中这行数据的最后一个历史版本;

MVCC的底层原理:
(1)操作的时候会生成事务id
①每条记录都会保存两个隐藏列:trx_id(事务id)和roll_pointer(回滚指针)2个字段;
②每次操作都会生成一条undo log日志,回滚指针指向前一条记录;
(2)查询的时候会生成一致性视图(ReadView):是由[未提交的事务id]+最大事务id组成,并根据一致性视图(ReadView)从undo log日志中从最新记录依次往下找:
① 如果事务id<未提交事务的最小id,则表示当前记录可读;
② 如果最小事务id<=事务id<=事务的最大id,需进一步判断事务id是否在未提交事务id的数组中,若在则不可读,若不在则可读;
③ 如果事务id>事务的最大id,则表示当前记录不可读;

一致性锁定读:
① 一致非锁定读,也可以称为快照读,其实就是普通的读取即普通SELECT语句;
② 既然是快照读,故 SELECT 的时候,会生成一个快照;
③ 生成快照的时机:事务中第一次调用SELECT语句的时候才会生成快照,在此之前事务中执行的update、insert、delete操作都不会生成快照;
④ 不同事务隔离级别下,快照读的区别:
1)READ COMMITTED (读已提交)隔离级别下,每次读取都会重新生成一个快照,所以每次快照都是最新的,也因此事务中每次SELECT也可以看到其它已commit事务所作的更改;
2)REPEATED READ(可重复读)隔离级别下,快照会在事务中第一次SELECT语句执行时生成,只有在本事务中对数据进行更改才会更新快照,因此,只有第一次SELECT之前其它已提交事务所作的更改你可以看到,但是如果已执行了SELECT,那么其它事务commit数据,你SELECT是看不到的;

1.5 Mysql中的锁

从锁粒度上区别:
(1)行锁:锁某行数据,锁粒度最小,并发度高;
(2)表锁:锁整张表,锁粒度最大,并发度低;
(3)间隙锁:锁的是一个区间;

从锁的类别上区别可以分为共享锁和排它锁:
1.共享锁:也就是读锁,一个事务对一个数据对象加了读锁,可以对这个数据对象进行读取操作,但不能进行更新操作,并且在加锁期间其它事务可以读,但是不能写;
2.排它锁:也就是写锁,一个事务对一个数据对象加了写锁,可以对这个数据对象进行读取和更新操作,但在加锁期间其它事务不能读,也不能写;

还可以分为:
1.乐观锁:每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在提交更新的时候会判断一下在此期间别人有没有去更新这个数据。(乐观锁实现方式,在表里面添加一个version字段,每次修改成功值加1,这样每次修改的时候先对比一下,自己拥有的version和数据库现在的version是否一致,如果不一致就不修改,这样就实现了乐观锁);
2.悲观锁:每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻止,直到这个锁被释放(上面所述的行锁、表锁都是悲观锁,实现方式:使用数据库中的锁机制);

1.6 Mysql如何解决死锁问题?

死锁是指两个或者两个以上进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象。在MySQL中,MyISAM是一次获得所需的全部锁,要么全部满足,要么等待,所以不会出现死锁。在InnoDB存储引擎中,除了单个SQL组成的事务外,锁都是逐步获得的,所以存在死锁问题;

常见的解决死锁方法有:
(1)如果不同程序会并发存取多个表,尽量约定以相同的顺序访问表,可以大大降低死锁机会;
(2)在同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁产生的概率;
(3)对于非常容易产生死锁的业务部分,可以尝试使用升级锁粒度,通过使用表级锁来减少死锁产生的概率;
(4)如果业务处理不好,可以用分布式事务锁或者使用乐观锁;

2 Mysql的索引

索引是满足某种特定查找算法的数据结构,而这些数据结构会以某种方式指向数据,从而实现高效查找数据。但会使修改、插入、删除操作变慢,同时还会占用较大的磁盘空间。

2.1 Mysql的聚簇和非聚簇索引的区别?

底层都是采用B+树的数据结构;
聚簇索引:将数据和索引放到一起存储,索引结构的叶子节点保留了数据行;

非聚簇索引:将数据进和索引分开存储,索引叶子节点存储的是指向数据行的地址;

在InnoDB存储引擎中,默认的索引为B+树索引,利用主键创建的索引为主索引,也是聚簇索引,在主索引之上创建的索引为辅助索引,也是非聚簇索引。为什么说辅助索引是在主索引之上创建的呢,因为辅助索引中的叶子节点存储的是主键;

在MyISAM存储引擎中,默认的索引也是B+树索引,但主索引和辅助索引都是非聚簇索引,也就是说索引结构的叶子节点存储的都是一个指向数据行的地址。并且使用辅助索引检索无需访问主键的索引;

聚簇索引的优点与缺点:
(1)优点:
①查询通过聚簇索引可以直接获取数据,相比非聚簇索引需要第二次查询,所以效率更高;
②聚簇索引对于范围查询的效率很高,因为其数据是按照大小排列的;
③聚簇索引适合用在排序的场合,而非聚簇索引不适合;
(2)缺点
①维护索引的代价很高,特别是插入新行或者主键被更新,而导致要分页的时候。建议在大量插入新行后,选在负载较低的时候,通过optimize table优化表,因为必须被移动的行数据可能造成碎片。使用独享表空间可以弱化碎片;
②表因为使用UUID或随机ID作为主键,使数据存储稀疏,这就会出现聚簇索引有可能比全表扫描更慢,所以建议使用int的auto_increment作为主键;
③如果主键比较大的话,那辅助索引将会变的更大,因为辅助索引的叶子存储时主键值,如果过长的主键值,会导致非叶子节点占用更多的物理空间;

2.2非聚簇索引一定会进行回表查询吗?

不一定,这涉及到索引覆盖的问题,也就是说查询语句所要求的字段是否全部命中了索引,如果全部命中了索引,那么就不必再进行回表查询。
举个例子:假如有一张用户信息表,包含id,name,age等字段,假设聚簇索引是以id为键值构建的索引,非聚簇索引是以name为键值构建的索引,当进行select id,name from user where name=’zhansan’,这个查询不需要回表查询,因为非聚簇索引已经能全部检索出数据,这就是索引覆盖的情况。如果是进行select id,name,age from user where name=’zhangsan’,这个查询时需要进行回表查询的,因为通过非聚簇索引不能检索出age的值,如何解决呢?只需要将索引覆盖即可,建立age和name的联合索引即可;

2.3简述在MySQL数据库中MyISAM和InnoDB的区别

(1)InnoDB
①InnoDB是Mysql的默认存储引擎,支持事务、行锁和外键等操作;
(2)MyISAM
①MyISAM是Mysql_5.1版本前的默认存储引擎,MyISAM的并发性比较差,不支持事务和外键等操作,默认的锁的粒度为表级锁;

MYSQL数据库面经_第2张图片

2.4 MyISAM索引与InnoDB索引的区别?

(1)InnoDB索引是聚簇索引,MyISAM索引是非聚簇索引;
(2)InnoDB的主键索引的叶子节点存储着行数据,因此主键索引非常高效;
(3)MyISAM索引的叶子节点存储的是行数据地址,需要再寻址一次才能得到数据;
(4)InnoDB非主键索引的叶子节点存储的是主键和其他带索引的列数据,因此查询时做到覆盖索引会非常高效;

2.5 为什么MyISAM在查询(Select)上性能比InnoDB速度快?

(1)InnoDB寻址要映射到块,再到行,MyISAM记录的直接是文件的offset,定位比InnoDB要快;
(2)InnoDB还需要维护MVCC的一致性;虽然你的场景没有,但它还是需要去检查和维护MVCC (Multi-Version Concurrency Control)多版本并发控制;
(3)InnoDB需要缓存数据块,MyISAM只缓存索引块, 这中间内存置换次数减少了;

2.6 Mysql索引的数据结构以及各自的优劣

索引的数据结构和具体存储引擎的实现有关,在Mysql中使用最多的索引有Hash索引、B+树索引等,InnoDB存储引擎的默认索引实现为:B+树索引。

Hash索引与B+树索引应用场景:
对于哈希索引,底层的数据结构就是哈希表,所以当在绝大多数需求为单条记录查询的时候,可以选择哈希索引,查询性能最快,其余部分场景,选择B+树索引;

Hash索引与B+数索引的区别:
① 如果是等值查询,哈希索引有明显的优势,因为只需要经过一次算法即可找到相应的键值(前提是键值都是唯一的)。如果键值不唯一的话,就需要先找到该键所在的位置,然后再根据链表往后扫描,直到找到相应的数据;
② 如果是范围查询,哈希索引就没用了,因为原先是有序的键值,经过哈希算法后,有可能变成不连续的了,就没有办法再利用索引完成范围查询检索;
③ 哈希索引也不支持多列联合索引的最左匹配规则;
④ 在存在有大量键值情况下,哈希索引的效率也是极低的,因为存在哈希碰撞问题;

2.7 Mysql中索引类型以及索引对数据库性能的影响

普通索引:允许被索引的数据列可以包含重复的值;
唯一索引:可以保证数据记录的唯一性;
主键索引:是一种特殊的唯一索引,在一张表中只能定义一个主键索引,主键用于唯一标识一条记录;
联合索引:索引可以覆盖多个数据列,如Index(col1,col2)
全文索引:通过建立倒排索引,可以极大的提升检索效率,解决判断字段是否包含的问题。

索引对数据库性能的影响:
(1)索引可以提高数据的查询速度;
(2)使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能;
(3)但是同时在使用索引后,也会降低插入、删除、更新表的速度,因为在执行这些写操作时,还要一边操作索引文件;
(4)索引还会占用一定的物理空间。

2.8主键索引与唯一索引的区别?

(1)主键创建后,一定包含唯一性索引,但是唯一性索引并不一定是主键;
(2)主键列不允许为空,但是唯一索引列可以允许为空;
(3)主键列其它表引用为外键,而唯一索引列不可以;
(4)一个表中,最多只能有一个主键索引,但是可以创建多个唯一索引;

2.9索引设计的原则

(1)适合索引的列是出现在where子句中的列,或者连接子句中指定的列;
(2)基数较小的表,索引效果较差,没有必要在此列建立索引;
(3)使用短索引,建立索引也是需要占用空间的,短索引可以节省大量索引空间;
(4)定义有外键的数据列,一定要建立索引;
(5)不要过度索引,索引需要额外的磁盘空间,并降低写操作的性能。

2.10唯一索引比普通索引更快吗?为什么?

唯一索引不一定比普通索引更快,有可能更慢;
(1)查询时,在未使用limit 1的情况下,在匹配到一条数据后,唯一索引即返回,普通索引会继续匹配下一条数据,发现不匹配后返回,如此看来唯一索引少了一次匹配,但实际上这个消耗是可以忽略不计的;
(2)更新时,普通索引将记录放到change buffer中,语句就执行完毕了。而对于唯一索引,它必须要校验唯一性,因此,必须将数据也读入内存确定没有冲突,然后才能继续操作,对于写多读少的情况,普通索引利用change buffer可以有效地减少了对磁盘的访问次数,因此,普通索引性能要高于唯一索引;

2.11什么时候需要使用索引,什么时候不需要使用索引?

可以通过explain语句对SQL语句进行分析,来决定哪些字段需要创建索引,一般情况下,可以得出以下结论:
(1)必须创建索引:
①where子句、group子句中出现的字段,需要创建索引;
②order by 子句的字段,需要创建索引;
③统计聚合函数中的字段,如min(字段)、count(字段)
(2)不需要创建索引:
①如果需要取到表中所有的数据,则没必要创建索引;
②对非唯一有大量重复值的字段,没必要创建索引,如性别;
③经常需要修改、删除的字段,没必要创建索引;
④记录比较少的表,没必要创建索引;

2.12 Mysql的最左匹配原则

例子:假如创建一个(a,b)的联合索引,那么它的索引树如下:
MYSQL数据库面经_第3张图片
可以看到a的值是有顺序的,1,1,2,2,3,3,而b的值是没有顺序的1,2,1,4,1,2。所以b = 2这种查询条件没有办法利用索引,因为联合索引首先是按a排序的,b是无序的;

同时我们还可以发现在a值相等的情况下,b值又是按顺序排列的,但是这种顺序是相对的。所以最左匹配原则遇上范围查询就会停止,剩下的字段都无法使用索引。例如a = 1 and b = 2 a,b字段都可以使用索引,因为在a值确定的情况下b是相对有序的,而a>1and b=2,a字段可以匹配上索引,但b值不可以,因为a的值是一个范围,在这个范围中b是无序的;

最左匹配原则:最左优先,从最左边为起点开始连续匹配,遇到范围查询(>、<、between、like)就会停止匹配;

(1)全值匹配查询时,用到了索引
select * from table_name where a = ‘1’ and b = ‘2’ and c = ‘3’
select * from table_name where b = ‘2’ and a = ‘1’ and c = ‘3’
select * from table_name where c = ‘3’ and b = ‘2’ and a = ‘1’
where子句几个搜索条件顺序调换不影响查询结果,因为Mysql中有查询优化器,会自动优化查询顺序;
(2) 匹配左边的列时
select * from table_name where a = ‘1’
select * from table_name where a = ‘1’ and b = ‘2’
select * from table_name where a = ‘1’ and b = ‘2’ and c = ‘3’
都从最左边开始连续匹配,用到了索引;
select * from table_name where b = ‘2’
select * from table_name where c = ‘3’
select * from table_name where b = ‘1’ and c = ‘3’
这些没有从最左边开始,最后查询没有用到索引,用的是全表扫描;
select * from table_name where a = ‘1’ and c = ‘3’
如果不连续时,只用到了a列的索引,b列和c列都没有用到;
(3)匹配范围值
select * from table_name where a > 1 and a < 3
可以对最左边的列进行范围查询;
select * from table_name where a > 1 and a < 3 and b > 1
多个列同时进行范围查找时,只有对索引最左边的那个列进行范围查找才用到B+树索引,也就是只有a用到索引,在1 1继续逐条过滤;
(4)精确匹配某一列并范围匹配另外一列
select * from table_name where a = 1 and b > 3
a=1的情况下b是有序的,进行范围查找走的是联合索引;
(5)匹配列前缀
select * from table_name where a like ‘As%’; //前缀都是排好序的,走索引查询
select * from table_name where a like ‘%As%’//全表查询
select * from table_name where a like ‘%As’//全表查询
如果a是字符类型,那么前缀匹配用的是索引,后缀和中缀只能全表扫描了;

7.2.13 like“%…”走索引吗?

都是 SELECT *
%在左边,即使有索引,也会失效
只有当%在右边时,才会生效

select * from table_name where a like ‘As%’; //前缀都是排好序的,走索引查询
select * from table_name where a like ‘%As’//全表查询
select * from table_name where a like ‘%As%’//全表查询

2.14什么情况下不走索引(索引失效)?

① 使用!=或者<>时,会导致索引失效;
② 数据类型不一致,导致索引失效;
1)select * from table where a = ‘1’ 会使用到索引;
2)如果写成 select * from table where a = 1 则会导致索引失效;
③ 函数导致索引失效;
1)SELECT * FROM user WHERE DATE(create_time) = ‘2020-09-03’;
④ 运算符导致索引失效;
1)SELECT * FROM user WHERE age - 1 = 20;
⑤ or引起的索引失效;
1)SELECT * FROM user WHERE name = ‘张三’ OR height = ‘175’;
2)or导致索引是在特定情况下的,并不是所有的or都是使索引失效,如果or连接的是同一个字段,那么索引不会失效,反之索引失效;
⑥ 模糊搜索导致的索引失效;
1)SELECT * FROM user WHERE name LIKE ‘%冰’;
2)当 % 放在匹配字段前是不走索引的,放在后面才会走索引;
⑦ not in、not exists导致索引失效;

2.15 B tree和B+tree的区别

(1)非叶子节点只存储键值(索引)信息
(2)数据记录都存放在叶子节点中
(3)所有叶子节点之间都有一个链指针(双向指针)

2.16为什么MySQL的索引要使用B+树而不是B树?

(1)B树适用于随机检索,而B+树适用于随机检索和顺序检索;
(2)B+树的空间利用率更高,因为B树每个节点要存储键和值,而B+树的内部节点只存储键,这样B+树的一个节点就可以存储更多的索引,从而使树的高度变低,减少了I/O次数,使得数据检索速度更快;
(3)B+树的叶子节点都是连接在一起的,所以范围查找,顺序查找更加方便;
(4)B+树的性能更加稳定,因为在B+树中,每次查询都是从根节点到叶子节点,而在B树中,要查询的值可能不在叶子节点,在内部节点就已经找到;

那在什么情况适合使用B树呢,因为B树的内部节点也可以存储值,所以可以把一些频繁访问的值放在距离根节点比较近的地方,这样就可以提高查询效率。综上所述,B+树的性能更加适合作为数据库的索引;

3 面试题

问题1:MySQL中存储索引用到的数据结构是B+树,B+树的查询时间跟树的高度有关,是log(n),若是用hash存储,那么查询时间是O(1)。既然hash比B+树更快,为何mysql用B+树来存储索引呢?
① 从内存角度上说,数据库中的索引通常是在磁盘上,数据量大的状况可能没法一次性装入内存,B+树的设计能够容许数据分批加载。
② 从业务场景上说,若是只选择一个数据那确实是hash更快,可是数据库中常常会选中多条数据,这时候因为B+树索引有序,而且又有链表相连,它的查询效率比hash就快不少了。

问题2:为何不用红黑树或者二叉排序树?
答:树的查询时间跟树的高度有关,B+树是一棵多路搜索树能够下降树的高度,提升查找效率。

问题3:为何B+树要这样设计?
答:这个跟它的使用场景有关,B+树在数据库的索引中用得比较多,数据库中select数据,不必定只选一条,不少时候会选中多条,好比按照id进行排序后选100条。若是是多条的话,B树须要作局部的中序遍历,可能要跨层访问。而B+树因为全部数据都在叶子结点不用跨层,同时因为有链表结构,只须要找到首尾,经过链表就能把全部数据取出来了。

4 数据库范式(三范式)

(1)第一范式
①属性不可再分;
(2)第二范式
①在第一范式的基础上,要求数据库表中的每个实例或行必须可以被唯一的区分,通常需要加上一个列,以存储各个实例的唯一标识,这个唯一属性列别称为主关键字或主键;
(3)第三范式
①在第二范式的基础上,要求一个数据库表中不包含已经其它表中已包含的非主关键字信息,所以第三范式具有如下特征:
1)每一列只有一个值;
2)每一行都能区分;
3)每一个表都不包含其它表已经包含的非主关键字信息;

5 数据库的设计原则

(1)一致性原则:对数据来源进行统一、系统的分析与设计,协调好各种数据源,保证数据的一致性和有效性;
(2)完整性原则:数据库的完整性是指数据的正确性和相容性,要防止合法用户使用数据库时向数据库加入不合语义的数据。对输入到数据库中的数据要有审核和约束机制;
(3)安全性原则:数据库的安全性是指保护数据,防止非法用户使用数据库或合法用户非法使用数据库造成数据泄露、更改或破坏,要有认证和授权机制;
(4)可伸缩性与可扩展性原则:数据库结构的设计应充分考虑发展的需要、移植的需要,具有良好的扩展性、伸缩性和适度冗余;
(5)规范性:数据库的设计遵循规范化理论,规范化的数据库设计,可以减少数据库插入、删除、修改等操作时的异常和错误,降低数据冗余度等;

6 Sql常见问题

6.1 distinct和group by在效率上的对比

(1)加了索引之后 distinct 比没加索引的 distinct 快了107倍;
(2)加了索引之后 group by 比没加索引的 group by 快了43倍;
(3)不管是加不加索引group by都比distinct快。因此使用的时候建议选 group by;

6.2 select count(*) 和select count(某个字段)有什么区别

(1)count(1) 会统计表中的所有的记录数,包含字段为null 的记录;
(2)count(*) 会统计表中的所有的记录数,包含字段为null 的记录;
(2)count(name) 会统计该字段在表中出现的次数,name字段为null 的情况。即不统计字段为null 的记录;

6.3 Union 和Union All区别

Union:对两个结果集进行并集操作,不包括重复行,同时进行默认规则的排序;
Union All:对两个结果集进行并集操作,包括重复行,不进行排序;

6.4 MySql中in和exists区别

in和exists一般都是用于子查询中,主要区别如下:
(1)使用exists时会先进行外表查询,将查询到的每行数据带入到内表查询中看是否满足条件;使用in一般会先进行内表查询获取结果集,然后对外表查询匹配结果集,返回数据;
(2)in在内表查询或者外表查询过程中都会用到索引;
(3)exists仅在内表查询时会用到索引;
(4)一般来说,当子查询的结果集比较大,外表较小使用exist效率更高;当子查询的结果集较小,外表较大时,使用in效率更高;

6.5 聚合函数与非聚合函数的区别?

聚合函数:是一种SQL基本函数,它是对一组数据值执行计算,并返回单个值。常用的聚合函数有:count、sum、avg、min、max。除了count以外,聚合函数都会忽略空值。聚合函数经常与 select语句的group by子句一起使用;
非聚合函数:也是一种SQL基本函数,它是一次处理一行数据,并返回单个值。常用的非聚合函数有:abs、length、concat、upper、lower、substring;

你可能感兴趣的:(Mysq,数据库,mysql,sql,hive,大数据)