数据库(SQL)面试题及答案

声明:此文档由本人学习整理所做,答案由个人整理,所引部分已经标出出处,牛友们按需查看,文章难免有纰漏错误之处,望交流指正。
题目摘自牛客网:大数据面试题V3.0,约870篇牛客大数据面经480道面试题 发布者:蓦_然 ,在此表达感谢。
数据库面试题(约3.9w字)

  1. 数据库中的事务是什么,MySQL中是怎么实现的
    事务(transaction)是作为一个单元的一组有序的数据库操作。如果组中的所有操作都成功,则认为事务成功,即使只有一个操作失败,事务也不成功。如果所有操作完成,事务则提交,其修改将作用于所有其他数据库进程。如果一个操作失败,则事务将回滚,该事务所有操作的影响都将取消。

前面讲的重做日志,回滚日志以及锁技术就是实现事务的基础。
事务的原子性是通过 undo log 来实现的
事务的持久性性是通过 redo log 来实现的
事务的隔离性是通过 (读写锁+MVCC)来实现的
而事务的终极大 boss 一致性是通过原子性,持久性,隔离性来实现的!!!
原子性,持久性,隔离性折腾半天的目的也是为了保障数据的一致性!
总之,ACID只是个概念,事务最终目的是要保障数据的可靠性,一致性。

  1. MySQL事务的特性?
    事务特性:

1、原子性:即不可分割性,事务要么全部被执行, 要么就全部不被执行。

2、一致性。事务的执行使得数据库从一种正确状态转换成另一种正确状态。

3、隔离性。在事务正确提交之前,不允许把该事务对数据的任何改变提供给任何其他事务。

4、持久性。事务正确提交后,其结果将永久保存在数据库中,即使在事务提交后有了其他故障,事务的处理结果也会得到保存。

  1. 数据库事务的隔离级别? 默认事务隔离级别?
    隔离性是事务ACID特性里最复杂的一个。在SQL标准里定义了四种隔离级别,每一种级别都规定一个事务中的修改,哪些是事务之间可见的,哪些是不可见的。
    级别越低的隔离级别可以执行越高的并发,但同时实现复杂度以及开销也越大。
    Mysql 隔离级别有以下四种(级别由低到高):
    ○ READ UNCOMMITED (未提交读)
    ○ READ COMMITED (提交读)
    ○ REPEATABLE READ (可重复读)(默认的事务隔离级别)
    ○ SERIALIZABLE (可重复读)

  2. 数据库事务的隔离级别解决了什么问题?
    只要彻底理解了隔离级别以及他的实现原理就相当于理解了ACID里的隔离性。那么隔离性是要做到什么呢? 隔离性是要管理多个并发读写请求的访问顺序。这种顺序包括串行或者是并行。

  3. 脏读,幻读,不可重复读的定义

  4. 脏读 :脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。

  1. 不可重复读 :是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。
    例如,一个编辑人员两次读取同一文档,但在两次读取之间,作者重写了该文档。当编辑人员第二次读取文档时,文档已更改。原始读取不可重复。如果只有在作者全部完成编写后编辑人员才可以读取文档,则可以避免该问题。
  1. 幻读 : 是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。
    例如,一个编辑人员更改作者提交的文档,但当生产部门将其更改内容合并到该文档的主复本时,发现作者已将未编辑的新材料添加到该文档中。如果在编辑人员和生产部门完成对原始文档的处理之前,任何人都不能将新材料添加到文档中,则可以避免该问题。

幻读和不可重复读是两个容易混淆的概念,幻读是指读到了其他已经提交事务的新增数据;不可重复读是指已经提交事务的更改数据(更改或删除)。
https://blog.csdn.net/bobozai86/article/details/110147719
6. MySQL怎么实现可重复读?
为什么会产生不可重复读?
这跟 READ COMMITTED 级别下的MVCC机制有关系,在该隔离级别下每次 select的时候新生成一个版本号,所以每次select的时候读的不是一个副本而是不同的副本。
在每次select之间有其他事务更新了我们读取的数据并提交了,那就出现了不可重复读

REPEATABLE READ(Mysql默认隔离级别)
在一个事务内的多次读取的结果是一样的。这种级别下可以避免,脏读,不可重复读等查询问题。mysql 有两种机制可以达到这种隔离级别的效果,分别是采用读写锁以及MVCC。
采用读写锁实现:

为什么能可重复度?只要没释放读锁,在次读的时候还是可以读到第一次读的数据。
优点:实现起来简单
缺点:无法做到读写并行
采用MVCC实现:

为什么能可重复度?因为多次读取只生成一个版本,读到的自然是相同数据。
优点:读写并行
缺点:实现的复杂度高
但是在该隔离级别下仍会存在幻读的问题,关于幻读的解决我打算另开一篇来介绍。
7. 数据库第三范式和第四范式区别?
第三范式:在二范式的基础上,不存在元素之间的传递函数依赖,则满足第三范式。

  1. MySQL的存储引擎?
  2. 存储引擎:存储数据,为存储的数据建立索引,更新、查询数据。

2.因为在关系数据库中数据以表的形式存储,所以,存储引擎也可以称为表类型。

3.查看当前MySQL数据库支持的存储引擎:show engines;或者show variablkes like 'have%';。

4.InnoDB存储引擎:
①是MySQL默认支持的数据库引擎。
②是事务安全的。
③支持外键。
④InnoDB存储引擎的表支持全文索引,大幅提升了InnoDB存储引擎的文本检索能力。
⑤InnoDB表空间分为共享表空间、独享表空间。
⑥适用场景:需要事务支持、行级锁定对高并发有很好地适应能力,但需要确保查询是通过索引完成、数据更新较为频繁。

5.MyISAM存储引擎:
①是老版本MySQL默认存储引擎。
②基于传统的ISAM类型。
③具有检查和修复表格的大多数工具。
④MyISAM表格可以被压缩,而且支持全文索引。
⑤不是事务安全的。
⑥不支持外键。
⑦不支持行级锁,支持表级锁。
⑧适用场景:不需要事务支持、并发相对较低、数据修改相对较少、以读为主、数据一致性要求不是特别高。

6.MEMORY存储引擎:
①将表中的数据存放在内存中,如果数据库重启或发生崩溃,表中的数据都将消失。
②适用于存储临时数据的临时表,以及数据仓库中的纬度表。

MySQL数据库使用MEMORY存储引擎作为临时表来存放查询结果集。

③默认使用哈希索引。
④只支持表锁。
⑤并发性能较差。
⑥不支持text和blob列类型。
⑦会浪费内存,比如:存储变长字段(varchar)时是按照定长字段(char)的方式进行的。

MyISAM和InnoDB的区别:
Ⅰ.InnoDB支持事务,而MyISAM不支持事务。
Ⅱ.InnoDB支持外键,而MyISAM不支持外键。
Ⅲ.InnoDB是行锁,而MyISAM是表锁(每次更新增加删除都会锁住表)。
Ⅳ.InnoDB和MyISAM的索引都是基于b+树,但他们具体实现不一样,InnoDB的b+树的叶子节点是存放数据的,MyISAM的b+树的叶子节点是存放指针的。
Ⅴ.InnoDB是聚簇索引,必须要有主键,一定会基于主键查询,但是辅助索引就会查询两次。MyISAM是非聚簇索引,索引和数据是分离的,索引里保存的是数据地址的指针,主键索引和辅助索引是分开的。
Ⅵ.InnoDB不存储表的行数,所以select count( * )的时候会全表查询。而MyISAM会存放表的行数,select count(*)的时候会查的很快。

————————————————
版权声明:本文为CSDN博主「忙起来,拿offer」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_48826058/article/details/123690955

  1. 数据库有哪些锁?
    行级锁
    行级锁是一种排他锁,防止其他事务修改此行;在使用以下语句时,Oracle 会自动应用行级锁:

INSERT、UPDATE、DELETE、SELECT … FOR UPDATE [OF columns] [WAIT n | NOWAIT];
SELECT … FOR UPDATE 语句允许用户一次锁定多条记录进行更新
使用 COMMIT 或 ROLLBACK 语句释放锁。

表级锁
表示对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分 MySQL 引擎支持。最常使 用的 MYISAM 与 INNODB 都支持表级锁定。表级锁定分为表共享读锁(共享锁)与表独占写锁 (排他锁)。

页级锁
页级锁是 MySQL 中锁定粒度介于行级锁和表级锁中间的一种锁。表级锁速度快,但冲突多,行级冲突少,但速度慢。所以取了折衷的页级,一次锁定相邻的一组记录。BDB 支持页级锁

数据库并发策略
并发控制一般采用三种方法,分别是乐观锁和悲观锁以及时间戳。

乐观锁

乐观锁认为一个用户读数据的时候,别人不会去写自己所读的数据;悲观锁就刚好相反,觉得自己读数据库的时候,别人可能刚好在写自己刚读的数据,其实就是持一种比较保守的态度; 时间戳就是不加锁,通过时间戳来控制并发出现的问题。

悲观锁

悲观锁就是在读取数据的时候,为了不让别人修改自己读取的数据,就会先对自己读取的数据加锁,只有自己把数据读完了,才允许别人修改那部分数据,或者反过来说,就是自己修改某条数 据的时候,不允许别人读取该数据,只有等自己的整个事务提交了,才释放自己加上的锁,才允 许其他用户访问那部分数据。

时间戳

时间戳就是在数据库表中单独加一列时间戳,比如“TimeStamp”,每次读出来的时候,把该字段也读出来,当写回去的时候,把该字段加 1,提交之前 ,跟数据库的该字段比较一次,如果比数据库的值大的话,就允许保存,否则不允许保存,这种处理方法虽然不使用数据库系统提供的锁机制,但是这种方法可以大大提高数据库处理的并发量,以上悲观锁所说的加“锁”,其实分为几种锁,分别是:排它锁(写锁)和共享锁(读锁)。
————————————————
版权声明:本文为CSDN博主「Django姜戈」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/programmer_union/article/details/117356077

  1. 说下悲观锁、乐观锁
    并发控制一般采用三种方法,分别是乐观锁和悲观锁以及时间戳。

乐观锁

乐观锁认为一个用户读数据的时候,别人不会去写自己所读的数据;悲观锁就刚好相反,觉得自 己读数据库的时候,别人可能刚好在写自己刚读的数据,其实就是持一种比较保守的态度;时间 戳就是不加锁,通过时间戳来控制并发出现的问题。

悲观锁

悲观锁就是在读取数据的时候,为了不让别人修改自己读取的数据,就会先对自己读取的数据加 锁,只有自己把数据读完了,才允许别人修改那部分数据,或者反过来说,就是自己修改某条数 据的时候,不允许别人读取该数据,只有等自己的整个事务提交了,才释放自己加上的锁,才允 许其他用户访问那部分数据。
————————————————
版权声明:本文为CSDN博主「Django姜戈」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/programmer_union/article/details/117356077

  1. 分布式数据库是什么?
    所谓的分布式数据库技术,就是数据库技术与分布式技术的一种结合。具体指的是把那些在地理意义上分散开的各个数据库节点,但在计算机系统逻辑上又是属于同一个系统的数据结合起来的一种数据库技术。既有着数据库间的协调性也有着数据的分布性。
    这个系统并不注重系统的集中控制,而是注重每个数据库节点的自治性,此外为了让程序员能够在编写程序时可以减轻工作量以及系统出错的可能性,一般都是完全不考虑数据的分布情况,这样的结果就使得系统数据的分布情况一直保持着透明性。
    数据独立性概念在分布式数据库管理系统中同样是十分重要的一环,但是不仅如此,分布式数据管理系统还增加了一个叫分布式透明性的新概念。这个新概念的作用是让数据进行转移时使程序正确性不受影响,就像数据并没有在编写程序时被分布一样。
    在分布式数据库里,数据冗杂是一种被需要的特性,这点和一般的集中式数据库系统不一样。第一点是为了提高局部的应用性而要在那些被需要的数据库节点复制数据。第二点是因为如果某个数据库节点出现系统错误,在修复好之前,可以通过操作其他的数据库节点里复制好的数据来让系统能够继续使用,提高系统的有效性。
    ————————————————
    版权声明:本文为CSDN博主「别吵我午休」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/m0_47575110/article/details/111303394

  2. 死锁产生的条件是什么?如何预防死锁?
    一、什么是死锁?
    死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。是操作系统层面的一个错误,是进程死锁的简称,最早在 1965 年由 Dijkstra 在研究银行家算法时提出的,它是计算机操作系统乃至整个并发程序设计领域最难处理的问题之一。
    二、死锁发生的原因?
    A:java 死锁产生的四个必要条件
    1、互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用
    2、不可抢占,资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。
    3、请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占有。
    4、循环等待,即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路。
    三、如何避免(预防)和解决死锁?
    A:死锁预防
    理解了死锁的原因,尤其是产生死锁的四个必要条件,就可以最大可能地避免、预防和解除死锁。只要打破四个必要条件之一就能有效预防死锁的发生
    有序资源分配法
    这种算法资源按某种规则系统中的所有资源统一编号(例如打印机为1、磁带机为2、磁盘为3、等等),申请时必须以上升的次序。系统要求申请进程:
    1、对它所必须使用的而且属于同一类的所有资源,必须一次申请完;
    2、在申请不同类资源时,必须按各类设备的编号依次申请。

银行家算法
避免死锁算法中最有代表性的算法是Dijkstra E.W 于1968年提出的银行家算法:
银行家算法是避免死锁的一种重要方法,防止死锁的机构只能确保上述四个条件之一不出现,则系统就不会发生死锁。

B:解决方法
在系统中已经出现死锁后,应该及时检测到死锁的发生,并采取适当的措施来解除死锁。

1、死锁预防
这是一种较简单和直观的事先预防的方法。方法是通过设置某些限制条件,去破坏产生死锁的四个必要条件中的一个或者几个,来预防发生死锁。预防死锁是一种较易实现的方法,已被广泛使用。但是由于所施加的限制条件往往太严格,可能会导致系统资源利用率和系统吞吐量降低。

2、死锁避免
系统对进程发出的每一个系统能够满足的资源申请进行动态检查,并根据检查结果决定是否分配资源;如果分配后系统可能发生死锁,则不予分配,否则予以分配。这是一种保证系统不进入死锁状态的动态策略。

3、死锁检测和解除
先检测:这种方法并不须事先采取任何限制性措施,也不必检查系统是否已经进入不安全区,此方法允许系统在运行过程中发生死锁。但可通过系统所设置的检测机构,及时地检测出死锁的发生,并精确地确定与死锁有关的进程和资源。检测方法包括定时检测、效率低时检测、进程等待时检测等。
然后解除死锁:采取适当措施,从系统中将已发生的死锁清除掉。
这是与检测死锁相配套的一种措施。当检测到系统中已发生死锁时,须将进程从死锁状态中解脱出来。常用的实施方法是撤销或挂起一些进程,以便回收一些资源,再将这些资源分配给已处于阻塞状态的进程,使之转为就绪状态,以继续运行。死锁的检测和解除措施,有可能使系统获得较好的资源利用率和吞吐量,但在实现上难度也最大。
如果我们在死锁检查时发现了死锁情况,那么就要努力消除死锁,使系统从死锁状态中恢复过来。消除死锁的几种方式:

1、最简单、最常用的方法就是进行系统的重新启动,不过这种方法代价很大,它意味着在这之前所有的进程已经完成的计算工作都将付之东流,包括参与死锁的那些进程,以及未参与死锁的进程;

2、撤消进程,剥夺资源。终止参与死锁的进程,收回它们占有的资源,从而解除死锁。这时又分两种情况:一次性撤消参与死锁的全部进程,剥夺全部资源;或者逐步撤消参与死锁的进程,逐步收回死锁进程占有的资源。一般来说,选择逐步撤消的进程时要按照一定的原则进行,目的是撤消那些代价最小的进程,比如按进程的优先级确定进程的代价;考虑进程运行时的代价和与此进程相关的外部作业的代价等因素;

3、进程回退策略,即让参与死锁的进程回退到没有发生死锁前某一点处,并由此点处继续执行,以求再次执行时不再发生死锁。虽然这是个较理想的办法,但是操作起来系统开销极大,要有堆栈这样的机构记录进程的每一步变化,以便今后的回退,有时这是无法做到的。

其实即便是商业产品,依然会有很多死锁情况的发生,例如 MySQL 数据库,它也经常容易出现死锁案例。
————————————————
版权声明:本文为CSDN博主「Tomsen_Tian」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/changfengxia/article/details/80313822

  1. 介绍下数据库的ioin(内连接,外连接,全连接),内连接和外连接(左,右连接)的区别

  2. MySQL的join过程
    总结:
    1、MySQL优先会将索引表当作被驱动表
    2、如果都两个表都有索引,会将小表当作驱动表
    3、如果两个表都没有索引,会将小表当作驱动表,将驱动表的数据全部加载到内存中,然后一行一行的读取被驱动表的数据,和内存中的驱动表数据进行比对
    4、如果驱动表的数据量超过了join_buffer的大小,会将驱动表分为多个段,一次只加载一段,然后一行一行的读取被驱动表的数据,进行比对。
    一个段比对完后,将join_buffer清空,继续下一个段的比对,但是还是要重新的从磁盘中加载被驱动表,虽然比较的次数没变,却重复的将被驱动表的数据从磁盘中读取到内存中,多了很多磁盘IO。

无论什么情况,都会将小表当作驱动表,小表指的是满足过滤条件后的表的数量,而不是表的原始规模。
————————————————
版权声明:本文为CSDN博主「张孟浩_jay」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_40276626/article/details/120774296

  1. 数据库中存储引擎MvlSAM与InnoDB的区别
    MyISAM和InnoDB的区别:
    Ⅰ.InnoDB支持事务,而MyISAM不支持事务。
    Ⅱ.InnoDB支持外键,而MyISAM不支持外键。
    Ⅲ.InnoDB是行锁,而MyISAM是表锁(每次更新增加删除都会锁住表)。
    Ⅳ.InnoDB和MyISAM的索引都是基于b+树,但他们具体实现不一样,InnoDB的b+树的叶子节点是存放数据的,MyISAM的b+树的叶子节点是存放指针的。
    Ⅴ.InnoDB是聚簇索引,必须要有主键,一定会基于主键查询,但是辅助索引就会查询两次。MyISAM是非聚簇索引,索引和数据是分离的,索引里保存的是数据地址的指针,主键索引和辅助索引是分开的。
    Ⅵ.InnoDB不存储表的行数,所以select count( * )的时候会全表查询。而MyISAM会存放表的行数,select count(*)的时候会查的很快。

  2. Mylsam适用于什么场景?
    1).[事务]MyISAM是⾮事务安全型的,⽽InnoDB是事务安全型的,默认开启⾃动提交,宜合并事务,⼀同提交,减⼩数据库多次提交导致的开销,⼤⼤提⾼性能。
    2).[锁]MyISAM锁的粒度是表级,⽽InnoDB⽀持⾏级锁定。
    3).[全⽂索引]MyISAM⽀持全⽂类型索引,⽽InnoDB不⽀持全⽂索引。
    4).[查询效率]MyISAM相对简单,所以在效率上要优于InnoDB,⼩型应⽤可以考虑使⽤MyISAM。
    5).[外健]MyISAM不⽀持外健,InnoDB⽀持。
    6).[count]MyISAM存有表的总⾏数,InnoDB只能遍历。
    6).MyISAM表是保存成⽂件的形式,在跨平台的数据转移中使⽤MyISAM存储会省去不少的⿇烦。
    7).InnoDB表⽐MyISAM表更安全,可以在保证数据不会丢失的情况下,切换⾮事务表到事务表(alter table tablenametype=innodb)。
    8)MyIsam索引和数据分离,InnoDB在⼀起,MyIsam天⽣⾮聚簇索引,最多有⼀个unique的性质,InnoDB的数据⽂件本⾝就是主键索引⽂件,这样的索引被称为“聚簇索引”
    9)InnoDB提供多版本数据⽀持 ,MyIsam不⽀持
    10)两者都仅⽀持B+树索引,不⽀持hash索引

应⽤场景:
1).MyISAM管理⾮事务表。它提供⾼速存储和检索,以及全⽂搜索能⼒。如果应⽤中需要执⾏⼤量的SELECT查询,那么MyISAM是更好的选择。(适用于查操作频繁)
2).InnoDB⽤于事务处理应⽤程序,具有众多特性,包括ACID事务⽀持。如果应⽤中需要执⾏⼤量的INSERT或UPDATE操作,则应该使⽤InnoDB,这样可以提⾼多⽤户并发操作的性能。(适用于增删改操作频繁)


作者:无太冬明明喆010
链接:https://wenku.baidu.com/view/a6822cf0b24e852458fb770bf78a6529647d3525.html
来源:百度文库
17. InnoDB和Mylsam针对读写场景?
MyISAM更适合读密集的表,而InnoDB更适合写密集的的表。
在数据库做主从分离的情况下,经常选择MyISAM作为主库的存储引擎。 一般来说,如果需要事务支持,并且有较高的并发读取频率(MyISAM的表锁的粒度太大,所以当该表写并发量较高时,要等待的查询就会很多了),InnoDB是不错的选择。如果你的数据量很大(MyISAM支持压缩特性可以减少磁盘的空间占用),而且不需要支持事务时,MyISAM是最好的选择。
————————————————
版权声明:本文为CSDN博主「machao1007」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/machao1007/article/details/109802589

  1. InnoDB用什么索引
    InnoDB 根据主键的顺序以索引的方式进行存储;
    默认采用B+树索引模型,数据都存储到B+树上;B+树是多叉树的一种
    InnoDB索引类型分为主键索引与非主键索引;
    (叶子结点就是没有子节点的节点)

1.1 主键索引: (也叫聚簇索引)
含义:把主键当作索引来使用,然后将对应的整行数据维护到B+树上。
特点:主键索引叶子结点中存储的是整行数据;

1.2 非主键索引:(也叫二级索引)
含义: 就是以其它字段(非主键)当作索引来使用,然后将对应数据维护到B+树上;
特点:二级索引叶子结点中存储的是主键的值;

1.3 主键索引与非主键索引的区别:
由于两者的特点不同,导致查询结果也不同;
主键索引只需查找一次B+树就可以定位到数据;
非主键索引需要查找两次B+树,首先根据二级索引查询到主键值,再根据主键值查询到整行数据!

1.4 索引是需要维护的:
所以,避免在增删改查操作较多的表中添加索引;
索引自身也是占用磁盘内存的;所以主键的字节尽量小一些。

1.5 索引的选择:
尽量选择主键索引;
主键长度越小越好;
尽量不要选择业务字段作为主键(例如身份证);
表数据过多再添加索引;
尽可能选择高基数列(就是不重复的列);
————————————————
版权声明:本文为CSDN博主「码出我天地」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/bruce_tao/article/details/105099127

  1. Hash索引缺点
    优点:
    因为索引自身只需存储对应的哈希值,所以索引的结构十分紧凑,这也让哈希索引查找的速度非常快。

缺点:
1、不能避免读取行
哈希索引只包含哈希值和行指针,而不存储字段值,所以不能使用索引中的值来避免读取行。不过,访问内存中的行的速度很快,所以大部分情况下这一点对性能的影响并不明显。
2、无法用于排序
哈希索引数据并不是按照索引值顺序存储的,所以也就无法用于排序。
3、无法使用部分索引列匹配查找
哈希索引也不支持部分索引列匹配查找,因为哈希索引始终是使用索引列的全部内容来计算哈希值的。例如,在数据列(A,B)上建立哈希索引,如果查询只有数据列A,则无法使用该索引。
4、只支持等值查找
哈希索引只支持等值比较查询,包括=、IN()、<=>(注意<>和<=>是不同的操作)。也不支持任何范围查询,例如WHERE price>100。
5、存在Hash冲突
访问哈希索引的数据非常快,除非有很多哈希冲突(不同的索引列值却有相同的哈希值)。当出现哈希冲突的时候,存储引擎必须遍历链表中所有的行指针,逐行进行比较,直到找到所有符合条件的行。
同时,当哈希冲突很多的时候,一些索引维护操作的代价也会很高。例如,如果在某个选择性很低(哈希冲突很多)的列上建立哈希索引,那么当从表中删除一行时,存储引擎需要遍历对应哈希值的链表中的每一行,找到并删除对应行的引用,冲突越多,代价越大。

综上,Hash索引只适用于某些特定的场景(也就是说实际使用中用得非常少-_-!)
————————————————
版权声明:本文为CSDN博主「鼬用天照」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/mzhnuaa/article/details/93473373

  1. 数据库索引的类型,各有什么优缺点?
    索引的数据结构:hash、二叉树、B树、B+树(最终最常用的是B+树)
    hash:使用存储在内存中的内容来创建表,而且数据全部存放在内存中。
    缺点:hash冲突–扰动函数
  2. Hash存储需将所有的数据文件添加到内存中,比较浪费内存空间
  3. 如果所有的查询都是等值查询,那么hash比较快,但范围查找就不太适合
    如果使用hash做成的索引,因为需求是全表扫描,即使在内存中,速度不容乐观。
    适合场景:等值查询的场景,就只有KV(Key,Value)的情况,例如Redis、Memcached等这些NoSQL的中间件。

二叉树:
叉树是有序的,所以是持范围查询的,但时间复杂度是O(log(N))。
缺点:二叉树还是红黑树都会因为树的深度过深而造成IO次数过多,影响读取效率,以及有可能退化为链表结构。
不推荐使用select * 而使用字段,因为数据是存储在磁盘,并且MySQL服务有筛选数据,每次读取数据都会经过服务筛选,如果都是使用select *就会增加io次数。

B树:
同样的元素,B树的表示要完全平衡叉树要“矮”,原因在于B树中的个节点可以存储多个元素,相对于完全平衡叉树整体的树降低了,磁盘IO效率提了。
从最开始的Hash不持范围查询,二叉树同样不支持,只有B树跟B+支持。

B+树

B+树非叶子节点上是不存储数据的,仅存储键值,而B树节点中不仅存储键值,也会存储数据。B+树所有的叶子节点形成一条有序链表(双向链表),而且数据是按照顺序排列的。

  1. MySQL的索引底层为何使用B+树?
    根据B+树的结构,我们可以发现B+树相比于B树,在文件系统,数据库系统当中,更有优势,原因如下:

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

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

3、B+树更有利于对数据库的扫描
B树在提高了磁盘IO性能的同时并没有解决元素遍历的效率低下的问题,而B+树只需要遍历叶子节点就可以解决对全部关键字信息的扫描,所以对于数据库中频繁使用的range query,B+树有着更高的性能

由于B+树的内部节点只存放键,不存放值,因此,一次读取,可以在内存页中获取更多的键,有利于更快地缩小查找范围。 B+树的叶节点由一条链相连,因此,当需要进行一次全数据遍历的时候,B+树只需要使用O(logN)时间找到最小的一个节点,然后通过链进行O(N)的顺序遍历即可。而B树则需要对树的每一层进行遍历,这会需要更多的内存置换次数,因此也就需要花费更多的时间。

————————————————
版权声明:本文为CSDN博主「静。弦」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_39799208/article/details/90668696

  1. MySQL的索引有哪些? 索引如何优化?
    索引优化
    最左前缀匹配原则。这事非常重要、非常重要、非常重要(重要的事情说三遍)的原则,MySQL会从左向右匹配直到遇到范围查询 (>,<,BETWEEN,LIKE)就停匹配。
    以最左边的为准,只要查询条件中带有最左边的列,那么查询就会使用到索引组合索引:当我们的where查询存在多个条件查询的时候,我们需要对查询的列创建组合索引,最左匹配一般组合索引一起使用。

回表:回表是发生在二级索引上的一种数据查询操作,简单点讲就是我们要查询的列不在二级索引的列中,那么就必须根据二级索引查到主键ID,然后再根据主键ID到聚簇索引树上去查询整行的数据,这一过程就叫作回表。

索引覆盖:当SQL语句中查询的列都在索引中时,我们就不需要回表去把整行数据都捞出来了,可以从非聚簇索引树中直接获取到我们需要的列的数据,这就叫索引覆盖。当所有的列都能在二级索引树中查询到,就不需要再回表了,这种情况就是索引覆盖,覆盖索引减少回表操作。

索引下推(推测):可以在索引遍历过程中,对索引中包含的字段先做判断,直接过滤掉不满条件的记录,减少回表次数。

使用ICP,当存在索引的列做为判断条件时,MySQL服务器将这一部分判断条件传递给存储引擎,然后存储引擎通过判断索引是否符合MySQL服务器传递的条件,只有当索引符合条件时才会将数据检索出来返回给MySQL服务器。
将与索引相关的条件由MySQL服务器向下传递至存储引擎,由此减少IO次数.索引条件下推优化可以减少存储引擎查询基础表的次数,也可以减少MySQL服务器从存储引擎接收数据的次数。
5.6之后才有,但有实际数据存储问题,唯一的缺点就是需要在磁盘上多做数据筛选,原来的筛选是放在内存中的,现在放在磁盘上进行,看起来成本比较高,但数据是排序的,所有的数据都是聚集存放,所以性能并不会受到影响,反而IO量会大大减少,提升性能。

索引失效条件
(1):条件是or,如果还想让or条件有效,给or每个字段加上索引
(2):like字段“%”开头
(3):如果列类型是字符串,那定要在条件中将数据使“”引起来,否则不会使索引(默认的类型转换调用类型转换函数,造成索引失效)
(4):where中索引列使用了函数或有运算操作会导致索引失效。

SQL优化
1、查询语句中不要使用select *
2、尽量减少子查询,使用关联查询(left join,right join,inner join)替代
3、减少使用IN或者NOT IN ,使用exists,not exists或者关联查询语句替代
4、or 的查询尽量用 union或者union all 代替(在确认没有重复数据或者不用剔除重复数据时,unionall会更好)
5、应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。
6、应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:select id from t where num is null 可以在num上设置默认值 0,确保表中num列没有null值,然后这样查询:select id from t where num=0

数据库索引优缺点
(1):需要查询,排序,分组和联合操作的字段适合建索引
(2):索引多,数据更新表越慢,尽量使字段值不重复比例的字段作为索引,联合索引效率高于多个独索引效率
(3):对数据进频繁查询进建索引,如果要频繁更改数据不建议使用索引
(4):当对表中的数据进增加、删除和修改的时候,索引也要动态的维护,降低了数据的维护速度。
https://baijiahao.baidu.com/sid=1677317239296034991&wfr=spider&for=pc

  1. B树与B+树的区别?
    ①B+树内节点不存储数据,所有 data 存储在叶节点导致查询时间复杂度固定为 log n。而B-树查询时间复杂度不固定,与 key 在树中的位置有关,最好为O(1)。
    B树的由于每个节点都有key和data,所以查询的时候可能不需要O(logn)的复杂度,甚至最好的情况是O(1)就可以找到数据,而B+树由于只有叶子节点保存了data,所以必须经历O(logn)复杂度才能找到数据

② B+树叶节点两两相连可大大增加区间访问性,可使用在范围查询等,而B-树每个节点 key 和 data 在一起,则无法区间查找。
由于B+树的叶子节点的数据都是使用链表连接起来的,而且他们在磁盘里是顺序存储的,所以当读到某个值的时候,磁盘预读原理就会提前把这些数据都读进内存,使得范围查询和排序都很快。

③B+树更适合外部存储。由于内节点无 data 域,每个节点能索引的范围更大更精确
由于B-树节点内部每个 key 都带着 data 域,而B+树节点只存储 key 的副本,真实的 key 和 data 域都在叶子节点存储。前面说过磁盘是分 block 的,一次磁盘 IO 会读取若干个 block,具体和操作系统有关,那么由于磁盘 IO 数据大小是固定的,在一次 IO 中,单个元素越小,量就越大。这就意味着B+树单次磁盘 IO 的信息量大于B-树,从这点来看B+树相对B-树磁盘 IO 次数少。
————————————————
版权声明:本文为CSDN博主「森明帮大于黑虎帮」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_44918090/article/details/120278339

  1. 为什么使用B+树作为索引结构?

https://blog.csdn.net/qq_44918090/article/details/120278339

  1. 不使用B+树,可以用那个数据类型实现一个索引结构
    B树,红黑树等

  2. 介绍下MySQL的联合索引及联合索使用原则
    索引的最左原则(左前缀原则),如(c1,c2,c3,c4....cN)的联合索引,where 条件按照索引建立的字段顺序来使用(不代表and条件必须按照顺序来写),如果中间某列没有条件,或使用like会导致后面的列不能使用索引。
    索引也能用于分组和排序,分组要先排序,在计算平均值等等。所以在分组和排序中,如果字段顺序可以按照索引的字段顺序,即可利用索引的有序特性。

  3. 数据库有必要建索引吗?
    索引创建
    适合创建所以的字段:
    where 条件
    order 排序字段
    join 的on 字段
    group by 字段

索引的数量不要过多
数据变动,索引也要跟着变,所以过多的索引不仅使更新操作变慢且浪费空间;

过长的字段建立前缀索引
离散度低的字段不要建立索引
区分度低的字段,因为和全表扫描效率差不多,优化器很可能会放弃使用所以,这样不仅没有提高查询效率,反而还要另外维护索引;

频繁更新的值,不要建立主键或索引
随机无序的值,不要建立索引
联合索引,把散列值(区分度)高的值放在前面

————————————————
版权声明:本文为CSDN博主「做一件事就好」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_41909330/article/details/119974455
28. MySQL缺点?
MySQL数据库的优缺点
优点:
体积小、速度快、总体拥有成本低,开源;
支持多种操作系统;是开源数据库,提供的接口支持多种语言连接操作
MySql的核心程序采用完全的多线程编程。线程是轻量级的进程,它可以灵活地为用户提供服务,而不过多的系统资源。用多线程和C语言实现的MySql能很容易充分利用CPU;
MySql有一个非常灵活而且安全的权限和口令系统。当客户与MySql服务器连接时,他们之间所有的口令传送被加密,而且MySql支持主机认证;
支持ODBC for Windows, 支持所有的ODBC 2.5函数和其他许多函数, 可以用Access连接MySql服务器, 使得应用被扩展;
支持大型的数据库, 可以方便地支持上千万条记录的数据库。作为一个开放源代码的数据库,可以针对不同的应用进行相应的修改。
拥有一个非常快速而且稳定的基于线程的内存分配系统,可以持续使用面不必担心其稳定性;
MySQL同时提供高度多样性,能够提供很多不同的使用者介面,包括命令行客户端操作,网页浏览器,以及各式各样的程序语言介面,例如C+,Perl,Java,PHP,以及Python。你可以使用事先包装好的客户端,或者干脆自己写一个合适的应用程序。MySQL可用于Unix,Windows,以及OS/2等平台,因此它可以用在个人电脑或者是服务器上;
缺点:
不支持热备份;
MySQL最大的缺点是其安全系统,主要是复杂而非标准,另外只有到调用mysqladmin来重读用户权限时才发生改变;
没有一种存储过程(Stored Procedure)语言,这是对习惯于企业级数据库的程序员的最大限制;
MySQL的价格随平台和安装方式变化。Linux的MySQL如果由用户自己或系统管理员而不是第三方安装则是免费的,第三方案则必须付许可费。Unix或Linux 自行安装 免费 、Unix或Linux 第三方安装 收费;
https://m.php.cn/article/190713.html

  1. 什么是脏读?怎么解决?
    用户正在对数据进行修改的同时,数据并没有持久化入磁盘,这时另一个用户对数据进行读操作,读到的数据是修改过后的数据。
    解决办法:redo 、 undo日志、锁机制、MVCC等

什么是脏读?
脏读又称无效数据的读出,是指在数据库访问中,事务T1将某一值修改,然后事务T2读取该值,此后T1因为某种原因撤销对该值的修改,这就导致了T2所读取到的数据是无效的,值得注意的是,脏读一般是针对于update操作的。

解决方法
mysql数据库定义了四种隔离级别:
○ serializable:可避免脏读、不可重复读、虚读情况的发生。
○ repeatable read:可以避免脏读、不可重复读情况的发生。
○ read committed:可以避免脏读情况发生。
○ read uncommitted:最低级别,都会发生。
注意:事务的隔离级别收到数据库的限制,不同的数据库支持的隔离级别不一定相同
脏读:修改时加排他锁,直到事务提交后才释放,读取时加上共享锁后(这样在事务1读取数据的过程中,其他事务就不会修改该数据),不允许任何事务操作该数据,只能读取,之后1如果有更新操作,那么会转换为排他锁,其他事务更无权参与进来读写,这样就防止了脏读问题
但是当事务1读取数据过程中,有可能其他事务也读取了该数据,读取完毕后共享锁释放,此时事务1修改数据,修改完毕提交事务,其他事务再次读取数据时候发现数据不一致,就会出现先不可重复读问题,所以这样不能够避免不可重复读问题
当执行不同的隔离级别时,可能会发生各种各样不同的问题。下面对他们进行总结并举例说明:
脏读发生在一个事务A读取了被另一个事务B修改,但是还未提交的数据。假如B回退,则事务A读取的是无效的数据。这跟不可重复读类似,但是第二个事务不需要执行提交。

  1. 为什么要有三大范式,建数据库时一定要遵循吗?
    这里可以将三大范式理解为:设计数据库时需要遵循的规则,可以有效的帮助我们建立冗余小且结构合理的数据库。

在概要设计阶段,同一个项目,10 个设计人员可能设计出 10 种不同的 E-R 图。不同的角度可以标识出不同的实体,实体又包括不同的属性,自然就设计出了不同的 E-R图。那么怎样审核这些设计图呢?如何评审出最优的设计方案呢?答案就藏在后面的内容里。

下面以某酒店的客人住宿信息表为例来介绍,该表用于保存酒店提供住宿的客房信息,如表 1 所示。

从用户的角度来说,将所有信息放在一个表中很方便,因为这样查询数据库可能会比较容易,但是上述表具有下列问题。

  1. 信息重复(冗余)
    上表中“客房类型”“客房状态”和“床位数”列中有许多重复的信息,如“标准间”“入住”等。信息重复会造成存储空间的浪费及一些其他的问题。比如,不小心输入了“标准间”和“标间”或“总统套房”和“总统套”,那么它们在数据库中将表示四种不同的客房类型。

  2. 更新异常
    冗余信息不仅浪费存储空间,还会增加更新的难度。如果需要将“客房类型”修改为“标间”而不是“标准间”,则需要修改所有包含该值的行。如果由于某种原因,没有更新所有行,那么数据库中会出现两种客房类型,一个是“标准间”,另一个是“标间”,这种情况被称为更新异常。

  3. 插入异常(无法表示某些信息)
    从表 1 中我们会发现 2002 和 2003 客房的居住价格分别是 168 元和 158 元。尽管这两间客房都是标准间类型,但它们的“价格”出现了不同,这样就造成了同一个酒店相同类型的客房价格不同,这种问题被称为插入异常。

  4. 删除异常(丢失有用的信息)
    在某些情况下,当删除一行时,可能会丢失有用的信息。例如,如果删除客房类型为“1001”的行,就会丢失客房类型为“单人间”的账户的信息,该表只剩下两种客房类型,即“标准间”和“总统套房”。当查询有哪些客房类型时,将会误以为只有“标准间”和“总统套房”两种客房类型,这种情况被称为删除异常。
    ————————————————
    版权声明:本文为CSDN博主「不善表演」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/weixin_44234912/article/details/108943823

  5. 数据库一般对哪些列建立索引? 索引的数据结构?
    数据库建立索引的常用规则如下:

  6. 表的主键和外键建立索引

  7. 在order by 或者 group by 后边建立索引

  8. 数据量超过300的应该建立索引

  9. 经常与其他表进行连接的表的字段,应该在该字段上建立索引
    5,经常出现在where子句中的字段应该建立索引,特别是大表字段

  10. 索引应该建立在选择性高的字段

  11. 复合索引在建立时应该仔细分析,尽量用单字段索引替代

不应该建立索引的字段规则
1.不应该在字段比较长的字段上建立索引,因为会消耗大量的空间
2.对于经常频繁进行修改和插入的表应该少建立索引,因为在修改和插入之后,数据库会去维护索引,会消耗资源
3.尽量少在无用字段上建立索引
————————————————
版权声明:本文为CSDN博主「ajungejava」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_37992974/article/details/102141060

  1. 关系型数据库与非关系型数据库区别

关系型和非关系型数据库的主要差异是数据存储的方式。关系型数据天然就是表格式的,因此存储在数据表的行和列中。数据表可以彼此关联协作存储,也很容易提取数据。(推荐教程:mysql视频教程)
与其相反,非关系型数据不适合存储在数据表的行和列中,而是大块组合在一起。非关系型数据通常存储在数据集中,就像文档、键值对或者图结构。你的数据及其特性是选择数据存储和提取方式的首要影响因素。
关系型数据库

关系型数据库最典型的数据结构是表,由二维表及其之间的联系所组成的一个数据组织
优点:
1、易于维护:都是使用表结构,格式一致;
2、使用方便:SQL语言通用,可用于复杂查询;
3、复杂操作:支持SQL,可用于一个表以及多个表之间非常复杂的查询。
缺点:
1、读写性能比较差,尤其是海量数据的高效率读写;
2、固定的表结构,灵活度稍欠;
3、高并发读写需求,传统关系型数据库来说,硬盘I/O是一个很大的瓶颈。
非关系型数据库

非关系型数据库严格上不是一种数据库,应该是一种数据结构化存储方法的集合,可以是文档或者键值对等。
优点:
1、格式灵活:存储数据的格式可以是key,value形式、文档形式、图片形式等等,文档形式、图片形式等等,使用灵活,应用场景广泛,而关系型数据库则只支持基础类型。
2、速度快:nosql可以使用硬盘或者随机存储器作为载体,而关系型数据库只能使用硬盘;
3、高扩展性;
4、成本低:nosql数据库部署简单,基本都是开源软件。
缺点:
1、不提供sql支持,学习和使用成本较高;
2、无事务处理;
3、数据结构相对复杂,复杂查询方面稍欠。
https://m.php.cn/article/463593.html

  1. MySQL与Redis区别
    mysql与redis的区别有:在类型上mysql是关系型数据库,而redis是缓存数据库;作用上mysql用于持久化的存储数据到硬盘,而redis用于存储使用较为频繁的数据到缓存中

mysql数据库
mysql是一种开放源代码的关系型数据库管理系统(RDBMS),MySQL数据库系统使用最常用的数据库管理语言(SQL)进行数据库管理。本部分主要内容包括:掌握结构化语言SQL,DDL创建数据库和表,Dos命令修改和删除库和表,DML命令增删改表数据,DQL命令查询表数据,数据库索引与备份

redis数据库
redis数据库就是一款缓存数据库,用于存储使用频繁的数据,这样减少访问数据库的次数,提高运行效率。

redis和mysql的区别
(1)类型上
从类型上来说,mysql是关系型数据库,redis是缓存数据库
(2)作用上
mysql用于持久化的存储数据到硬盘,功能强大,但是速度较慢
redis用于存储使用较为频繁的数据到缓存中,读取速度快
(3)需求上
mysql和redis因为需求的不同,一般都是配合使用。
https://m.php.cn/article/418150.html

  1. 列式数据库和行式数据库优劣比对
    查询方面的对比:
    先来说行式数据库,通过上面我们知道数据是一行一行的存贮起来的,我们如果想要查询,那么就会一行行的扫描,从而得到我们的数据。还用上面的例子,假定我们只想要name这一列的数据,我们是不是查询的时候也必须把其他的数据顺便给查出来了,因为他们是一起的。那我们就知道了,即使我们只想要一列的数据,也得整行扫描,多的那些数据都是磁盘IO,不得不需要加上额外的不需要的数据。
    然后再来说列式数据库,通过上面我们也知道了列式数据库式按照一列一列来存贮的。再来看上面的那个查询问题,我们依旧只想要name这一列,这个时候我们就只需要把这一列查询出来就行了,其他的没有关系的我们也不关心,是不是瞬间就减少了数据量呀,这个优点尤其是在海量数据的时候尤其明显,查询速度秒杀行式数据库。
    接着我们再返回行式数据库想一下,比如mysql在做查询优化的时候,最常用的手段就是建立索引,可是我们想一想,数据量一旦大的时候,索引也会成倍的增长。
    而列式数据库则不然,他的每一列就是索引,减少了额外建立索引的内容。
    当然了,如果我们的需求就是查询所有字段,那个这个时候列式数据库的处理方式就是先把所有列查询出来,然后再拼接起来,速度方面是比不上行式数据库的。不过我们既然用到了列式数据库,那么我们的场景需求就是大量数据,一般在大数据领域,进行所有字段的查询的这个要求少之又少,所以这个缺点我们需要正视,但是我们也可以忽略。

压缩比较
行式数据库因为存贮数据是一行行的来存贮,而每一行数据的差异性太大,所以压缩比很小。列式数据库则不同,因为是按照一列列来存贮,每一列的数据的相同性极高,这就为压缩埋下了很好的种子,压缩比可以达到很大,可以达到5~20倍以上。
接下来看一下网上的一个图来说明问题。

我认为这个压缩比是这种列式存贮在面对海量数据存贮查询的时候灵魂。因为拥有超高的压缩比,在磁盘iO传输的时候,据统计可以达到行式的100倍以上。
当然了,拥有超高的压缩比,另外一方面可以减少磁盘的使用率,不过在现在这个硬盘不值钱的年代,这个优点也不是啥大优点了,最重要的还是在磁盘IO的传输上。

应用场景比较
行式数据库主要应用于传统的业务场景中
列式数据库则应该发挥他查询速度方面的优势,主要用于海量数据分析一类的方面。
https://zhuanlan.zhihu.com/p/79320135

  1. 除了UTF-8还有什么编码格式
    常见的编码格式有ASCII、ANSI、GBK、GB2312、UTF-8、GB18030和UNICODE等。
  2. 布隆过滤器的基本原理是什么?局限性是什么?使用什么方法可以增加删除的功能?
    引言
    之所以谈到布隆过滤器主要是因为以前工作中用到redis,为了防止缓冲穿透而使用了布隆过滤器(BloomFilter)。这次温故而知新,再深入学习它的原理,顺带提提它的其他用途。

1、简介
简单来说,布隆过滤器(BloomFilter)是一种数据结构。特点是存在性检测,如果布隆过滤器中不存在,那么实际数据一定不存在;如果布隆过滤器中存在,实际数据不一定存在。相比于传统数据结构(如:List、Set、Map等)来说,它更高效,占用空间更少。缺点是它对于存在的判断是具有概率性。
2、实现原理
在谈到原理之前,我们先来看看布隆过滤器的数据结构,它是一个bit数组。如下图所示:

这是一个长度为8,默认都是0的bit数组。如果我们想要映射一个值到布隆过滤器中,怎么操作呢?首先是使用多个不同的哈希函数生成多个哈希值,再把哈希值指向的bit位置1。例如:我们要将值“baidu”映射到布隆过滤器上,怎么操作呢?假如我们使用三个不同的哈希函数生成了三个哈希值分别是:1、3、6,那么上图就转变为下图这样:

从图中看出,标有浅蓝色的bit位的值都被置为1,表示该数据已经映射上了。接着我们再把值“alibaba”和三个不同哈希函数生成的值:2、6、8映射到上面布隆过滤器中,它就会变为下图的样子:

很显然,它把之前映射的哈希值6覆盖了,这就是布隆过滤器是有误报率的一个因素。如果这时候,我们想拿一个未插入映射的值“tencent”查询它是否在上面布隆过滤器中存在。该怎么操作呢?首先,把值“tencent”用上面三个不同哈希函数生成三个哈希值分别是:2、4、6;再去布隆过滤器上找这三个值对应的bit位的值是否都是1,我们发现2和6都返回了1,而4返回0,说明值“tencent”没有做过映射,即不存在。实际上我们并没有事先做过此值的插入映射操作。这当然是正确的。
https://blog.csdn.net/lotus35/article/details/114005198

HBase中读数据时候,查询数据是否存在于读缓存中时使用了布隆过滤器。

  1. 你在哪些场景下使用了布隆过滤器?
    典型应用场景
    ○ 黑名单:比如邮件黑名单过滤器,判断邮件地址是否在黑名单中;
    ○ 网络爬虫:判断某个URL是否已经被爬取过;
    ○ K-V系统快速判断某个key是否存在:典型的例子有Hbase,Hbase的每个Region中都包含一个BloomFilter,用于在查询时快速判断某个key在该region中是否存在,如果不存在,直接返回,节省掉后续的查询。
    ○ 搜索引擎中的海量网页去重;
    ○ leveldb等数据库中快速判断元素是否存在,可以显著减少磁盘访问;

  2. SQL慢查询的解决方案(优化)?
    ● 一、前言
    ● 二、慢查询概要
    ○ 2.1 第一步,慢查询分析之前的配置
    ■ 2.1.1 方式一:修改my.ini
    ■ 2.1.2 方式二:修改数据库
    ○ 2.2 第二步,找到执行慢的sql语句
    ○ 2.3 第三步,找到原因两种方式之一,explain分析,explain各个字段的解释
    ○ 2.4 第四步,找到原因两种方式之一,profile分析,找到慢查询的本质原因,profile各个字段的解释
    ■ 2.4.1 explain制造慢sql语句,profile找到慢的sql语句
    ■ 2.4.2 show profile for query 具体id
    ● 2.4.2.1 sending data发送数据慢,就是网络IO
    ● 2.4.2.2 Copying to tmp table临时表慢
    ■ 2.4.3 查看cpu、内存和IO信息
    ● 三、SQL优化
    ○ 3.1 第一,明确SQL优化两个目标(IO成本+CPU成本)
    ○ 3.2 第二,SQL执行的11个步骤,搞懂MySQL的语句执行顺序(11条)
    ○ 3.3 第三,表设计(表设计5条 + 字段设计5条)
    ■ 3.3.1 表设计层面(5条)
    ■ 3.3.2 字段设计层面(5条)
    ○ 3.4 第四,高效的SQL语句(索引+单表优化+多表优化)
    ■ 3.4.1 索引(索引两方向:优先使用索引,避免索引失效)
    ● 3.4.1.1 避免索引失效
    ● 3.4.1.2 优先使用索引
    ■ 3.4.2 单表查询 10点
    ● 1、单表查询:避免索引失效,不要在 where 子句中对字段进行 null 值判断,这会进行全表扫描
    ● 2、单表查询,开启慢查询日志,定位慢查询的SQL语句
    ● 3、单表查询,数据库压力转移到Java后台
    ● 4、单表查询,where 查询条件数量 + 查询条件顺序
    ● 5、单表查询,返回值和关键字大写优化(select ,limit)
    ● 6、单表查询:计数优化,不要使用 count(列名)或 count(常量)来替代 count(
    )
    ● 7、单表查询:去重优化,能用GROUP BY的就不用DISTINCT
    ● 8、单表查询,LIMIT优化,巧借索引优化orderby排序
    ● 9、单表查询:排序优化,order by 字段加索引
    ● 10、单表查询:分组优化,group by 调节顺序为复合索引顺序
    ■ 3.4.3 多表连接查询 4点
    ● 1、多表连接,五个:用 join 代替子查询,连接字段类型一致,连接字段加索引,主表是小表,orderby和groupby字段在主表,否则无用
    ● 2、多表查询,很多时候用exists代替in是一个好的选择(理由:虽然in与exists效率在不同场景效率有高有低,但not exists比not in的效率高)
    ● 3、尽量避免向客户端返回大数据量,应该使用分页
    ● 4、用Union ALL代替OR(比较少用,一般都用OR)
    ○ 3.5 第五,通用
    ● 四、小结
    https://blog.csdn.net/weixin_44842613/article/details/117409984

  3. 聚簇索引、非聚簇索引说一下
    聚簇索引 & 非聚簇索引
    聚集索引与非聚集索引的区别是:由主键字段建立的索引叫主键索引,而非主键字段建立的索引叫非主键索引。
    InnoDB 主键使用的是聚簇索引,MyISAM 不管是主键索引,还是二级索引使用的都是非聚簇索引。

1.对于 非聚簇索引表来说(右图),表数据和索引是分成两部分存储的,主键索引和二级索引存储上没有任何区别。使用的是B+树作为索引的存储结构,所有的节点都是索引,叶子节点存储的是索引+索引对应的记录的数据。
2.对于 聚簇索引表来说(左图),表数据是和主键一起存储的,主键索引的叶结点存储行数据(包含了主键值),二级索引的叶结点存储行的主键值。使用的是B+树作为索引的存储结构,非叶子节点都是索引关键字,但非叶子节点中的关键字中不存储对应记录的具体内容或内容地址。叶子节点上的数据是主键与具体记录(数据内容)。

聚簇索引的优点
1.当你需要取出一定范围内的数据时,用聚簇索引也比用非聚簇索引好。
2.当通过聚簇索引查找目标数据时理论上比非聚簇索引要快,因为非聚簇索引定位到对应主键时还要多一次目标记录寻址,即多一次I/O。
3.使用覆盖索引扫描的查询可以直接使用页节点中的主键值。

聚簇索引的缺点

  1. 插入速度严重依赖于插入顺序,按照主键的顺序插入是最快的方式,否则将会出现页分裂,严重影响性能。因此,对于InnoDB表,我们一般都会定义一个自增的ID列为主键。

  2. 更新主键的代价很高,因为将会导致被更新的行移动。因此,对于InnoDB表,我们一般定义主键为不可更新。

  3. 二级索引访问需要两次索引查找,第一次找到主键值,第二次根据主键值找到行数据。
    二级索引的叶节点存储的是主键值,而不是行指针(非聚簇索引存储的是指针或者说是地址),这是为了减少当出现行移动或数据页分裂时二级索引的维护工作,但会让二级索引占用更多的空间。

  4. 采用聚簇索引插入新值比采用非聚簇索引插入新值的速度要慢很多,因为插入要保证主键不能重复,判断主键不能重复,采用的方式在不同的索引下面会有很大的性能差距,聚簇索引遍历所有的叶子节点,非聚簇索引也判断所有的叶子节点,但是聚簇索引的叶子节点除了带有主键还有记录值,记录的大小往往比主键要大的多。这样就会导致聚簇索引在判定新记录携带的主键是否重复时进行昂贵的I/O代价。
    https://blog.csdn.net/weixin_33750452/article/details/91398777

  5. MVCC知道吗?
    MVCC
    MVCC,全称Multi-Version Concurrency Control,即多版本并发控制。MVCC是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问,在编程语言中实现事务内存。

多版本控制: 指的是一种提高并发的技术。最早的数据库系统,只有读读之间可以并发,读写,写读,写写都要阻塞。引入多版本之后,只有写写之间相互阻塞,其他三种操作都可以并行,这样大幅度提高了InnoDB的并发度。
MVCC在MySQL InnoDB中的实现主要是为了提高数据库并发性能,用更好的方式去处理读-写冲突,做到即使有读写冲突时,也能做到不加锁,非阻塞并发读。

什么是当前读和快照读?
在学习MVCC多版本并发控制之前,我们必须先了解一下,什么是MySQL InnoDB下的当前读和快照读?
当前读
像select lock in share mode(共享锁), select for update ; update, insert ,delete(排他锁)这些操作都是一种当前读,为什么叫当前读?就是它读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁。

快照读
像不加锁的select操作就是快照读,即不加锁的非阻塞读;快照读的前提是隔离级别不是串行级别,串行级别下的快照读会退化成当前读;之所以出现快照读的情况,是基于提高并发性能的考虑,快照读的实现是基于多版本并发控制,即MVCC,可以认为MVCC是行锁的一个变种,但它在很多情况下,避免了加锁操作,降低了开销;既然是基于多版本,即快照读可能读到的并不一定是数据的最新版本,而有可能是之前的历史版本
说白了MVCC就是为了实现读-写冲突不加锁,而这个读指的就是快照读, 而非当前读,当前读实际上是一种加锁的操作,是悲观锁的实现

MVCC带来的好处是?
多版本并发控制(MVCC)是一种用来解决读-写冲突的无锁并发控制,也就是为事务分配单向增长的时间戳,为每个修改保存一个版本,版本与事务时间戳关联,读操作只读该事务开始前的数据库的快照。 所以MVCC可以为数据库解决以下问题
在并发读写数据库时,可以做到在读操作时不用阻塞写操作,写操作也不用阻塞读操作,提高了数据库并发读写的性能同时还可以解决脏读,幻读,不可重复读等事务隔离问题,但不能解决更新丢失问题。
https://www.cnblogs.com/xuwc/p/13873611.html

#大数据开发实习##实习##笔试题目##面经#
全部评论
感谢分享,都是比较经典的啊
1
送花
回复
分享
发布于 2022-05-12 14:36
点赞
送花
回复
分享
发布于 2023-03-04 22:53 浙江
滴滴
校招火热招聘中
官网直投

相关推荐

20 229 评论
分享
牛客网
牛客企业服务