面试整理-数据库部分

目录

 

1、数据库学习笔记

1、什么是存储过程?有哪些优缺点?与函数有什么区别?与触发器有什么区别?

2、三个范式是什么?

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

4、什么是触发器?

5、什么是游标?

6、SQL

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

8、什么是事务?

9、什么是共享锁?互斥锁?

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

11、数据库运行于哪种状态下可以防止数据的丢失?

12、varchar和char的区别?

13、数据库连接

14、数据库优化的思路

15、数据库死锁如何防止?

16、索引在什么情况下失效?

17、Union和union all的区别?

18、用distinct和用group by去重,谁的效率更高?

19、Mysql的Innodb和MyIASM引擎。

20、ROW_NUMBER() OVER函数的基本用法


1、数据库学习笔记

1、什么是存储过程?有哪些优缺点?与函数有什么区别?与触发器有什么区别?

SQL语句执行的时候要先编译然后再被执行。在大型数据库系统中,为了提高效率,将为了完成特定功能的SQL语句集进行编译优化后,存储在数据库服务器中,用户通过指定的存储过程的名字来调用执行。存储过程是一组预编译的SQL语句。

优点:

  1. 可以将代码封装起来;
  2. 保存在数据库之中;
  3. 让编译语言进行调用;
  4. 存储过程是一个预编译的代码块,执行效率比较高。
  5. 一个存储过程替代大量Sql语句,可以降低网络通信量,提高通信速率。

缺点:

  1. 每个数据库的存储过程语法都不一样,十分难以维护。
  2. 业务逻辑放在数据库上,难以迭代。

与函数的区别:

  1. 存储过程是预编译的,执行效率比函数高。
  2. 存储过程可以不返回任何值,也可以返回多个输出变量,但函数有且必须返回一个值。
  3. 存储过程必须单独执行,而函数可以嵌入表达式中,使用更灵活。
  4. 存储过程主要是用于对逻辑处理的应用或解决,函数主要是一种功能应用或解决。

与触发器的区别:

         存储过程必须有用户、应用程序或者触发器来显示的调用并执行,而触发器是当特定时间出现的时候,自动执行或者激活的,与连接用数据库中的用户、或者应用程序无关。

2、三个范式是什么?

第一范式:每个属性不可再分

第二范式:消除部分依赖,满足第一范式,表中的非主属性必须完全依赖于主键(全部主属性)

第三范式:消除传递依赖,满足第二范式,非主属性必须互不依赖

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

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

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

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

4、什么是触发器?

触发器是一种特殊类型的存储过程,它由事件触发,而不是程序调用或手工启动。当数据库有特殊自操作时,对这些操作由数据库中的事件来触来自动完成这些SQL语句。使用触发器可以月来保证数据的有效性和完整性,完成比约束更复杂的数据约束。根据SQL语句的不同,触发器可分为两类:DML触发器和DLL触发器。

DML触发器是当数据库服务器发生数据操作语言事件时执行的存储过程,有After和Instead Of两种触发器。After触发器被激活触发是在记录改变之后进行的一种触发器。Instead Of触发器是在记录变更之前,去执行触发器本身所定义的操作,而不是执行原来SQL语句里的操作。DLL触发器是在响应数据定义语言事件时执行的存储过程。

触发器主要作用表现在以下几个方面:

  1. 增加安全性。
  2. 利用触发器记录所进行的修改以及相关信息,跟踪用户对数据库的操作,实现审计。
  3. 维护那些通过创建表时的声明约束不可能实现的复杂的完整性约束以及对数据库中特定事件进行监控与响应。
  4. 实现复杂的非标准的数据库相关完整性规则、同步实时地复制表中的数据。
  5. 触发器是自动的,它们在对表的数据做了任何修改之后就会被激活。例如,可以自动计算数据值,如果数据的值达到了一定的要求,则进行特定的处理。以某企业财务管理为例,如果企业的资金链出现短缺,并且达到某种程度时,则发送警告信息。

引申:触发器分为事前触发和事后触发,两者有什么区别?语旬组触发和行组触发有什么区别?

    事前触发发生在事件发生之前验证一些条件或进行有一些准备工作;事后触发器发生在事件发生之后,做收尾工作,保证事务的完整性。而事前触发可以获得之前和新的字段值。语句级触发器可以在语句执行之前或之后执行,而行级触发在触发器所影响的每一行触发一次。

5、什么是游标?

在数据库中,游标提供了一种对从表中检索出的数据进行操作的灵活手段。它实际上是一种能从包括多条数据记录的结果集中每次提取一条记录的机制。

游标总是与一条SQL选择语句相关联,因为游标由结果集(可以是零条、一条或由相关的选择语句检索出的多条记录)和结果集中指向特定记录的游标位置组成。当决定对结果集进行处理时,必须声明一个指向该结果集的游标。

游标允许应用程序对查询语句select返回的行结果集中每一行进行相同或不同的操作,而不是一次对整个结果集进行同一种操作。它还提供对基于游标位置而对表中数据进行删除或更新的能力。而且,正是游标把作为面向集合的数据库管理系统和面向行的程序设计两者联系起来,使两个数据处理方式能够进行沟通。

游标的优点有以下两个方面的内容:

  1. 在使用游标的表中,对行提供删除和更新的能力。
  2. 游标将面向集合的数据库管理系统和面向行的程序设计连接了起来。

6、SQL

(1)Drop、delete与truncate的区别以及应用场景。

drop table

1)属于DDL

2)不可回滚

3)不可带where

4)表内容和结构删除

5)删除速度快

truncate table

1)属于DDL

2)不可回滚

3)不可带where

4)表内容删除

5)删除速度快

delete from

1)属于DML

2)可回滚

3)可带where

4)表结构在,表内容要看where执行的情况

5)删除速度慢,需要逐行删除

应用场景:

1、 不再需要一张表的时候,用drop

2、 想删除部分数据行时候,用delete,并且带上where子句

3、 保留表而删除所有数据的时候用truncate

(2)SQL约束有几种?

NOT NULL: 用于控制字段的内容一定不能为空(NULL)。

UNIQUE: 控件字段内容不能重复,一个表允许有多个 Unique 约束。

PRIMARY KEY: 也是用于控件字段内容不能重复,但它在一个表只允许出现一个。

FOREIGN KEY: 用于预防破坏表之间连接的动作,也能防止非法数据插入外键列,因为它必须是它指向的那个表中的值之一。

CHECK:用于控制字段的值范围。

DEFAULT: 用于设置新记录的默认值。

(3)SQL注入是什么?如何避免?

  1. sql注入:用户输入的数据,未经检测,变成了sql语句的一部分被执行,造成意外的结果输出。
  2. 避免sql注入:避免数据变成代码被执行,对sql语句进行预编译和查询参数绑定,在SQL语句中放置占位符'?',然后将带有占位符的SQL语句传给数据库编译,执行的时候才将用户输入的数据作为执行的参数传给数据库。这样的操作不仅使得SQL语句在书写的时候不再需要拼接,看起来也更直接,而且用户输入的数据也没有机会被送到数据库的SQL解释器被编译执行,也不会越权变成代码。
  3. 实例:登录界面用户名输入:admin' or 1=1 '

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

索引的定义:

索引是与表或视图关联的磁盘上结构,即对表中列值排序的一种结构 ,可以加快从表或视图中检索行的速度,执行查询时不必扫描整个表就能更快速的访问数据库中的信息。

一条索引记录包含键值和逻辑指针。创建索引时,系统分配一个索引页。在表中插入一行 数据,同时也向该索引页中插入一行索引记录。索引记录包含的索引字段值比真 实数据量小,节省了空间。

索引的特点:

  1. 索引一旦建立,*Oracle管理系统会对其进行自动维护*,而且由Oracle管理系统决定何时使用索引。
  2. 用户不用再查询语句中指定使用哪个索引。
  3. 在定义primary key或unique约束后系统自动在相应的列上创建索引。
  4. 用户也能按照自己的需求,对指定单个或多个字段添加索引。

索引的使用场景:

何时要创建索引:

  1. 表经常进行SELECT操作
  2. 表很大(记录超多),记录内容分布范围很广。
  3. 列名经常在WHERE子句或链接条件中出现。

何时不用创建索引:

  1. 表经常进行INSERT/UPDATE/DELETE操作。
  2. 表很小。
  3. 列名不经常作为连接条件或出现在WHERE子句中。

索引优缺点:

  1. 索引加快数据库的检索速度
  2. 索引降低了插入、删除、修改等维护任务的速度。
  3. 唯一索引可以确保每一行数据的唯一性,通过索引,可以在查询的过程中使用优化隐藏器,提高系统的性能。
  4. 索引需要占用物理和数据空间。

索引分类:

  1. 唯一索引:唯一索引不允许两行具有相同的索引值。
  2. 主键索引:为表定义一个主键将自动创建主键索引,主键索引是唯一索引的特殊类型。主键索引要求主键中的每个值是唯一的,并且不能为空。
  3. 聚簇索引:表中各行的物理顺序与键值的逻辑(索引)顺序相同,每个表只能有一个。
  4. 非聚集索引:非聚集索引指定表的逻辑顺序。数据存储在一个位置,索引存储在另一个位置,索引中包含指向数据存储位置的指针。可以有多个,小于249个。
  5. 全文索引(倒排索引)

索引的实现方式:

1、B+

首先介绍B树:

B+树的特点:

  1. 有n棵子树的结点中含有n个关键字,每个关键字不保存数据,只用来索引,所有数据都保存在叶子节点。
  2. 所有的叶子结点中包含了全部关键字的信息,及指向含这些关键字记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接。
  3. 所有的非终端结点可以看成是索引部分,结点中仅含其子树(根结点)中的最大(或最小)关键字。

通常在B+树上有两个头指针,一个指向根结点,一个指向关键字最小的叶子结点。

与B树的比较:

  1. 所有的叶子结点中包含了全部关键字的信息,及指向含有这些关键字记录的指针,且叶子结点本身依关键字的大小自小而大的顺序链接。(而B 树的叶子节点并没有包括全部需要查找的信息)
  2. 所有的非终端结点可以看成是索引部分,结点中仅含有其子树根结点中最大(或最小)关键字。(而B 树的非终节点也包含需要查找的有效信息)

我们经常听到B+树就是这个概念,用这个树的目的和红黑树差不多,也是为了尽量保持树的平衡,当然红黑树是二叉树,但B+树就不是二叉树了,节点下面可以有多个子节点,数据库开发商会设置子节点数的一个最大值,这个值不会太小,所以B+树一般来说比较矮胖,而红黑树就比较瘦高了。ORACLE的默认索引就是这种结构的。

如果经常需要同时对两个字段进行AND查询,那么使用两个单独索引不如建立一个复合索引,因为两个单独索引通常数据库只能使用其中一个,而使用复合索引因为索引本身就对应到两个字段上的,效率会有很大提高。

2、散列索引

通过散列函数来定位的一种索引,不过很少有单独使用散列索引的,反而是散列文件组织用的比较多。

散列文件组织就是根据一个键通过散列计算把对应的记录都放到同一个槽中,这样的话相同的键值对应的记录就一定是放在同一个文件里了,也就减少了文件读取的次数,提高了效率。

散列索引就是根据对应键的散列码来找到最终的索引项的技术,其实和B树就差不多了,也就是一种索引之上的二级辅助索引,我理解散列索引都是二级或更高级的稀疏索引,否则桶就太多了,效率也不会很高。

3、位图索引

位图索引是一种针对多个字段的简单查询设计的一种特殊的索引,适用范围比较小,只适用于字段值固定并且值的种类很少的情况,比如性别,只能有男和女,或者级别,状态等等,并且只有在同时对多个这样的字段查询时才能体现出位图的优势

位图的基本思想就是对每一个条件都用0或者1来表示,如有5条记录,性别分别是男,女,男,男,女,那么如果使用位图索引就会建立两个位图,对应男的10110和对应女的01001,这样做有什么好处呢,就是如果同时对多个这种类型的字段进行and或or查询时,可以使用按位与和按位或来直接得到结果了MySQL不支持。

三种索引实现方式的比较:

  1. B+树最常用,性能也不差,用于范围查询和单值查询都可以。特别是范围查询,非得用B+树这种顺序的才可以了。
  2. HASH的如果只是对单值查询的话速度会比B+树快一点,但是ORACLE好像不支持HASH索引,只支持HASH表空间。
  3. 位图的使用情况很局限,只有很少的情况才能用,一定要确定真正适合使用这种索引才用(值的类型很少并且需要复合查询,比如性别),否则建立一大堆位图就一点意义都没有了。

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

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

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

  1. 基于一个范围的检索,一般查询返回结果集小于表中记录数的30%。
  2. 基于非唯一性索引的检索。

对于建立索引的列,数据是均匀分布好还是不均匀分布好?

数据均匀分布比较好。最好每条记录的索引列的值各不相同,比如ID,这样查找效率最高。比如年龄,对于千万级的大表,分布还是太集中了,加上索引也没有太大用处。

比如有一个字段是性别,需要加索引吗?又扯到了位图索引。

不需要。性别不是男就是女,这种列加了索引也没有什么用。也可以加位图索引。

8、什么是事务?

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

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:第一种是(WAL)Write ahead logging,也就是日志式的方式。第二种是Shadow paging。

Write ahead logging(预写日志):

1. 事务所引起的所有改动都要记录在日志中,在事务提交完成之前,所有的这些记录必须被写入硬盘;

2. 一个数据库的缓冲页直到被记入日志后才能发生修改。直到缓冲页对应的日志被写入硬盘后,该缓冲页才会存入硬盘;

3. 当缓冲页被修改和日志被更新修改时,必须加上互斥锁,以保证改动被记录到日志中的顺序与它发生的顺序是一致的。

以上规则的结果:

如果一条日志记录未被存入硬盘,则它可以被忽略,因为该日志中包含的改动一定属于未提交的事务。此外,这样的日志不能反映已持久化在数据库中的改动;

日志记录按顺序记录系统的改动。加锁协议(latch protocol)保证如果有对于同一页改动的两条日志记录,则两条记录的顺序反映对页发生改变的顺序。

事务隔离级别:

读未提交(Read uncommitted):允许读取还未提交的改变了的数据。可能导致脏、幻、不可重复读。

读已提交(Read committed):允许在并发事务已经提交后读取。可防止脏读,但是幻读和不可重复读仍可发生。

可重复读(Repeatable read):对相同字段的多次读取是一致的,除非数据被事务本身改变。可防止脏、不可重复读,但是幻读仍可能发生。

串行化(Serializable):完全服从数据库四种隔离级别,确保不发生脏、幻、不可重复读。速度最慢,它是通过完全锁定在事务中涉及的数据表来完成的,事务按顺序串行执行。

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

脏读:一个事务读取了另一个事务改写但还未提交的数据,如果这些数据被回滚,则读到的数据是无效的。读到无效数据,导致查询结果前后不一致。

不可重复读:在同一个事务中,读到另一个事务已经提交更新的数据。读到更新的数据,导致多次读取同一个数据返回的结果有所不同。

幻读:一个事务读取了几行记录后,另一个事务插入一些记录,幻读就发生了。在后来的查询中,第一个事务就会发现有些原来没有的记录。读取到新的记录

MySQL的默认事务隔离级别是Repeatable read。

9、什么是共享锁?互斥锁?

在数据库中,锁主要是对数据进行读/写的一种保护机制,从数据库系统的角度来看,一般可以将锁分为共享锁和互斥锁。共享锁简称S锁,也叫读锁。用于不更改或不更新数据的操作(只读操作),如select语句。如果事务T对数据A加上共享锁后,则其他事务只能对A再加共享锁,不能加排他锁。共享锁可阻止其他并发运行的程序获取重叠的独占锁定,但是允许该程序获取重叠的共享锁定。其他用户可以获取共享锁锁定的资源,但是不能进行修改该共享锁。在执行select命令时,SQL Server 通常会对对象进行共享锁锁定。若事务T对数据D加S锁,则其他事务只能对D加S 锁,而不能加X锁,直至T释放D上的S锁;一般要求在读取数据前要向该数据加共享锁,所以共享锁又称为读锁。通常加共享锁的数据页被读取完毕后 ,共享锁就会立即被释放。互斥锁简称X锁,也叫排他锁,用于数据修改操作,如insert、update或delete。确保不会同时对同一资源进行多重更新。为了保证数据操作的完整性,引入了互斥锁。用互斥锁来保证在任意时刻,只能有一个线程访问对象。若事务T对数据D加X锁,则其他任何事务都不能再对D加任何类型的锁,直至T释放D上的X锁;一般要求在修改数据前要向该数据加排他锁,所以排他锁又称为写锁。

而对于锁的使用,也有一定的限制,需要遵守两个事项:

1)先锁后操作;2)事务结束之后必须解锁。

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

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

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

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

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

11、数据库运行于哪种状态下可以防止数据的丢失?

在archivelog mode(归档模式)只要其归档日志文件不丢失,就可以有效地防止数据丢失。

12、varchar和char的区别?

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

13、数据库连接

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

1. 加载JDBC驱动程序

2. 提供JDBC连接的URL

3. 创建数据库的连接

4. 创建一个Statement

5. 执行SQL语句

6. 处理结果

7. 关闭JDBC对象

14、数据库优化的思路

SQL优化:

1、选择最有效的表名顺序

数据库的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后的表将被最先处理。

如果三个表是完全无关系的话,将记录和列名最少的表,写在最后,然后依次类推,也就是说:选择记录条数最少的表放在最后。如果三个表是有关系的话,将引用最多的表,放在最后,然后依次类推,被其他表所引用的表放在最后。

2、WHERE子句中的链接顺序

数据库采用自右而左的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之左,那些可以过滤掉最大数量记录的条件必须写在WHERE子句的之右。

3、SELECT子句中避免使用*号

4、用TRUCATE替代DELETE

DELETE是一条一条记录的删除,而Truncate是将整个表删除,保留表结构,这样比DELETE快

5、多使用内部函数提高SQL效率

例如使用mysql的concat()函数会比使用||来进行拼接快,因为concat()函数已经被mysql优化过了。

6、使用表或列的别名

如果表或列的名称太长了,使用一些简短的别名也能稍微提高一些SQL的性能。毕竟要扫描的字符长度就变少了

7、多使用commit

comiit会释放回滚点

8、善用索引

索引就是为了提高我们的查询数据的,当表的记录量非常大的时候,我们就可以使用索引了。

9、SQL写大写

我们在编写SQL 的时候,官方推荐的是使用大写来写关键字,因为Oracle服务器总是先将小写字母转成大写后,才执行

10、避免在索引上使用NOT

因为Oracle服务器遇到NOT后,他就会停止目前的工作,转而执行全表扫描

11、避免在索引上使用计算

WHERE子句中,如果索引列是函数的一部分,优化器将不使用索引而使用全表扫描,这样会变得变慢

12、用>=替代>

13、用IN替代OR

14、总是使用索引的第一个列

如果索引是建立在多个列上,只有在它的第一个列被WHERE子句引用时,优化器才会选择使用该索引。 当只引用索引的第二个列时,不引用索引的第一个列时,优化器使用了全表扫描而忽略了索引。(从左到右的使用索引中的字段,一个查询可以只使用索引中的一部份,但只能是最左侧部分。例如索引是key index (a,b,c)。 可以支持a | a,b| a,b,c 3种组合进行查找,但不支持 b,c进行查找 ,当最左侧字段是常量引用时,索引就十分有效。)

数据库结构优化:

  1. 范式优化: 比如消除冗余(节省空间。。)
  2. 反范式优化:比如适当加冗余等(减少join)
  3. 拆分表: 垂直拆分和水平拆分

服务器硬件优化:

提高机器性能。

15、数据库死锁如何防止?

1、事务之间对资源的访问顺序的交替

出现原因:

一个用户A 访问表A(锁住了表A),然后又访问表B;另一个用户B 访问表B(锁住了表B),然后企图访问表A;这时用户A由于用户B已经锁住表B,它必须等待用户B释放表B才能继续,同样用户B要等用户A释放表A才能继续,这就死锁就产生了。

解决方案:

这种死锁比较常见,是由于程序的BUG产生的,除了调整的程序的逻辑没有其它的办法。仔细分析程序的逻辑,对于数据库的多表操作时,尽量按照相同的顺序进行处理,尽量避免同时锁定两个资源,如操作A和B两张表时,总是按先A后B的顺序处理, 必须同时锁定两个资源时,要保证在任何时刻都应该按照相同的顺序来锁定资源

2、并发修改同一条记录

出现原因:

主要是由于没有一次性申请够权限导致的。

用户A查询一条纪录,然后修改该条纪录;这时用户B修改该条纪录,这时用户A的事务里锁的性质由查询的共享锁企图上升到独占锁,而用户B里的独占锁由于A有共享锁存在所以必须等A释放掉共享锁,而A由于B的独占锁而无法上升的独占锁也就不可能释放共享锁,于是出现了死锁。这种死锁比较隐蔽,但在稍大点的项目中经常发生。

解决方案:

a. 乐观锁,实现写-写并发

b. 悲观锁:使用悲观锁进行控制。悲观锁大多数情况下依靠数据库的锁机制实现,如Oracle的Select … for update语句,以保证操作最大程度的独占性。但随之而来的就是数据库性能的大量开销,特别是对长事务而言,这样的开销往往无法承受。

3、索引不当导致的死锁

如果在事务中执行了一条不满足条件的语句,执行全表扫描,把行级锁上升为表级锁,多个这样的事务执行后,就很容易产生死锁和阻塞。类似的情况还有当表中的数据量非常庞大而索引建的过少或不合适的时候,使得经常发生全表扫描,最终应用系统会越来越慢,最终发生阻塞或死锁。

解决方案:

SQL语句中不要使用太复杂的关联多表的查询;

使用“执行计划”对SQL语句进行分析,对于有全表扫描的SQL语句,建立相应的索引进行优化。

如何避免死锁?

  1. 以固定的顺序访问表和行。即按顺序申请锁,这样就不会造成互相等待的场面。
  2. 大事务拆小。大事务更倾向于死锁,如果业务允许,将大事务拆小。
  3. 在同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁概率。
  4. 降低隔离级别。如果业务允许,将隔离级别调低也是较好的选择,比如将隔离级别从RR调整为RC,可以避免掉很多因为gap锁造成的死锁。
  5. 为表添加合理的索引。如果不走索引将会为表的每一行记录添加上锁,死锁的概率大大增大。

16、索引在什么情况下失效?

原因:

  1. 对单字段建立索引,where条件多字段
  2. 复合索引失效,where条件没有按照复合索引的顺序排列
  3. 对索引列运算,运算符包括(+、-、*、/、!、<>、%、like'%_'(%放在前面)、or、in、exist等),比如where a+1=c
  4. 类型错误,字段类型为varchar,where条件用number
  5. 对索引使用内部函数,这种情况下应该建立基于函数的索引
  6. is null 索引失效,is not null 索引有效
  7. where子句中使用参数,select id from t where num=@num。

17、Union和union all的区别?

  1. 两者都是合并结果集,但是从使用和效率上都有所不同。
  2. 对重复结果的处理:UNION在进行表链接后会筛选掉重复的记录,Union All不会去除重复记录。
  3. 对排序的处理:Union将会按照字段的顺序进行排序;UNION ALL只是简单的将两个结果合并后就返回。
  4. 从效率上说,UNION ALL 要比UNION快很多,所以,如果可以确认合并的两个结果集中不包含重复数据且不需要排序时的话,那么就使用UNION ALL。

18、用distinct和用group by去重,谁的效率更高?

区别:distinct简单来说就是用来去重的,而group by的设计目的则是用来聚合统计的,两者在能够实现的功能上有些相同之处,但应该仔细区分,因为用错场景的话,效率相差可以倍计。

效率:加了索引之后 distinct 比没加索引的distinct 快了107倍。加了索引之后 group by 比没加索引的group by 快了43倍。再来对比 :distinct 和group by不管是加不加索引group by 都比distinct快。因此使用的时候建议选 group by。

19、Mysql的Innodb和MyIASM引擎。

Innodb引擎:

  1. 支持事务
  2. 提供了行级锁和外键约束(锁的粒度是row)
  3. 存储容量为64TB
  4. 支持哈希索引,不支持全文索引。
  5. 启动比较慢,而且不会保存表的行数。当进行Select count(*) from table指令的时候,需要进行扫描全表

注意:Innodb是基于索引来实现行锁的。

例: select * from tab_with_index where id = 1 for update;

for update 可以根据条件来完成行锁锁定,并且 id 是有索引键的列,如果 id 不是索引键那么InnoDB将完成表锁,,并发将无从谈起。

MyIASM引擎:

  1. 不支持事务
  2. 不支持行级锁和外键约束(锁的粒度是table)
  3. 存储容量没有上限
  4. 支持全文索引,不支持哈希索引。
  5. 保存了表的行数。当进行Select count(*) from table语句时,可以直接的读取已经保存的值而不需要进行扫描全表。

应用场景:

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

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

  1. 对于MyIASM引擎来说,B+树的数据结构中存储的内容实际上是实际数据的地址值。也就是说它的索引和实际数据是分开的,只不过使用索引指向了实际数据。这种索引的模式被称为非聚集索引。
  2. 而Innodb引擎的索引的数据结构也是B+树,只不过数据结构中存储的都是实际的数据,这种索引有被称为聚集索引

20、ROW_NUMBER() OVER函数的基本用法

语法:ROW_NUMBER() OVER(PARTITION BY COLUMN ORDER BY COLUMN)

样例1:

ROW_NUMBER() OVER (ORDER BY xlh DESC)

简单的说row_number()从1开始,为每一条分组记录返回一个数字,这里的ROW_NUMBER() OVER (ORDER BY xlh DESC) 是先把xlh列降序,再为降序以后的没条xlh记录返回一个序号。

样例2:

row_number() OVER (PARTITION BY COL1 ORDER BY COL2) 表示根据COL1分组,在分组内部根据 COL2排序,而此函数计算的值就表示每组内部排序后的顺序编号(组内连续的唯一的)。

SELECT *, Row_Number() OVER (partition by deptid ORDER BY salary desc) rank FROM employee

猜你喜欢

转载自blog.csdn.net/u013094043/article/details/82823832
今日推荐