sql面试基础知识总结

总结了一些sql基础知识及概念:

1.delete与truncate的区别?

1)truncate的速度远快于delete,原因是:当执行delete操作时所有哦表数据先被 copy到回滚表空间,而truncate则是直接删除表结构及数据。
2)delete删除后可以进行rollback进行回滚,而truncate则直接删除不能回滚。
3)truncate不能带where子句只能删除全部表数据,delete可指定条件删除。

2.集合操作符

union:不包含重复值,默认按第一个查询的第一列升序排序。
union all:完全并集包含重复值,不排序。
minus:不包含重复值,不排序。

3.数据库的三大范式是什么?

1)第一范式:原子件,要求每一列的值不能再拆分了。
2)第二范式:一张表只能描述一个实体(若有冗余列,则不满足)。
3)第三范式:所有列与主键值直接相关。

4.什么是事务?

事务是数据库操作的最小单元,是作为单个逻辑单元执行的一系列逻辑操作,这些操 作作为一个整体全部要么执行、要么不执行。

5.事务的四个特性(ACID)是什么?

1)原子性(Atomic):事务中的各项操作,要么全做要么全不做,任何一项操作额失败都会导致整个事务的失败。
2)一致性(Consistent):事务结束后系统状态是一样的。
3)隔离性(Isolated):并发执行的事务彼此无法看到对方的中间状态。
4)持久性(Durable):事务完成后,可以通过日志或者同步备份重建数据库。

6.事务的并发问题?

1)脏读:事务A读取了事务B更新的数据,然后B执行了回滚操作,那么A读到的数据是脏数据;
2)不可重复读:事务A多次读取同一数据,事务A在事务B多次读取的过程中,对事务进行了更新并提交,导致事务A在多次读取同一数据时结果不一致;
3)幻读:举例,系统管理员A将数据库中的所有学生成绩由具体分数改成ABCDE等级,但是系统管理员B在此时插入了一条具体分数的记录,当A更改结束后发现还有一条记录没有更改过来,就像发生了幻觉一样,就叫幻读;
总结:不可重复读和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读问题只需锁住操作行,解决幻读需要锁表。

7.事务的隔离级别(isolation)?

事务的隔离级别 说明 脏读 不可重复读 幻读
读未提交 一个事务可以读取另一个事务未提交的数据
读提交(sql server和oracle默认) 一个事务要等另一个事务提交后才能读取数据
可重复读(mysql默认) 开始允许读取数据时(事务开启),不能再修改数据
串行化 事务串行化顺序执行

说明:
1)事务隔离级别为读提交时,写数据只会锁住相应的行;
2)事务隔离级别为串行化时,读写都会锁住整张表;
3)隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大;
参照: https://blog.csdn.net/qq_33290787/article/details/51924963

8.mysql和oracle数据库的区别?

1)自增数据类型方面,mysql有自动增长的数据类型,oracle没有,需要建立一个自增序列。
2)group by用法,mysql中group by子句可以在select 中随意使用,但是在oracle中如果查询语句中有group by子句,那么要查询的列必须是组函数处理过的或是group by中的列。
3)字符串引号,mysql中可以用单引号或多引号包起字符串,oracle中只能使用单引号包起字符串。

9.pl/sql中的游标,为什么要使用游标?

游标是执行sql语句时在系统内存中创建的临时工作区。游标的作用就是用于临时存储从数据库中农存取的数据块。
优点:在某些情况下,需要把数据从存放在磁盘的表中加载到内存中进行处理,最后将处理结果显示出来或重写回数据库,对数据进行统一的处理、提交(先查出数据并锁定,不会出现并发访问问题),这样数据处理速度才会提高,否则频繁的磁盘数据交换会降低效率。
缺点:锁定的数据过多,并发大的时候反而会降低性能;数据频繁更新时数据同步会有很大消耗。
使用参照:https://www.cnblogs.com/xiaoliu66007/p/7495753.html

10.oracle中函数(function)和存储过程(procedure)的区别?

1)可以理解函数是存储过程的一种;
2)函数可以没有参数,但是一定要有返回值,存储过程可以没有参数,不需要返回值,可以通过out返回多个参数;
3)在数据操纵语言(DML,增删改查)中只能调用函数而不能调用存储过程。

11.oracle中存储单位

1)data block 数据块,是oracle最小的逻辑单元,通常oracle从磁盘中读取的就是块。
2)extent 区,由若干个相邻的块组成。
3)segment 段,由一组区组成。
4)tablespace 表空间,数据库中逻辑存储的地方,一个表空间可以存放多个数据文件(*.dbf)。

12.oracle锁机制

1)当多个用户并发的操作同一数据表或数据行时,那么就会存在多个事务操作同一资源的现象,如果不会并发操作进行控制,就会破坏数据库的一致性。
2)加锁可以实现数据库的并发控制,当事务在对某个数据对象进行caozuo9前,先向系统发出请求,对其加锁,加锁后事务就对该数据对象有了一定的控制,在该事务释放锁之前,其他事务不能对此数据对象进行操作。
3)oracle锁机制不是通过构建锁列表实现对数据的锁定管理,而是直接将锁作为数据块的属性,存储在数据块首部。这个地方叫ITL(Interested Transaction List),凡是在这个数据块上有活动的事务,它的信息就会记录在这里面供后续的操作,保证事务的一致性。
详细参照https://www.cnblogs.com/zhoading/p/8547320.html

13.oracle中的锁?

1)按用户与系统划分:
自动锁,当进行一项数据库操作时,缺省情况下,系统自动为此操作获得所有有必要的锁。
显示锁,用户显示地锁定数据库操作要用到的数据,才能使数据库操作更好的执行。
2)按级别划分:
共享锁,共享锁使事务对数据库资源进行共享访问,为事务提供高并发性,但是拙劣的事务设计+共享锁容易造成死锁或数据更新丢失。
排它锁,事务设置排它锁后,该事务获得此资源后另一事务不能在此事务提交之前获得相同对象的 共享锁或排它锁。
3)按操作划分:
DML锁:
行级锁,当事务执行数据库插入、更新是、删除时,该事务自动获得操作表中操作行的排它锁。
表级锁,当事务获得行锁后,该事务也将自动获得改行的表锁(共享锁),以防止其他事务进行DDL(表操作)操作影响记录行的更新。只有当事务显示地使用lock table语句显示地定义一个排它锁时,事务才能获得表上的排它锁。
死锁,当两个事务需要一组有冲突(需要的锁正是对方正在占用而不能释放)的锁,而不能将事务继续进行下去,就会出现死锁。

14.oracle悲观锁和乐观锁?

1)悲观锁,顾名思义,就是很悲观,每次去拿数据的时候认为别人会修改,所以在每次拿的时候都对数据进行上锁,这样别人只有等待锁的释放才能拿到数据。当执行select xxx for update 操作时,只有进行commit或rollback后资源才会被释放。
2)乐观锁,就是很乐观,每次拿数据的时候后会认为别人不会修改,所以不会上锁,但是在更新的时候会判断在此期间别人有没有去更新这条数据。oracle默认使用乐观锁。乐观锁与悲观锁的区别是没有将数据进行锁定,在此期间其他会话也可共享此资源,只不过在提交时互斥而已,可以解决并发性能问题。
判断别人有无更新数据的方式,一般采用版本戳或时间戳的方式。首先在乐观锁的数据库的表上建立一个新的列作为更新版本,当每次进行数据更新时就将版本号加1,当一个session在拿到数据进行更新后,在提交时查看到当前数据的版本与拿到时相同,则进行数据提交,并将版本号加1,则其他session与此同时也在修改这条数据并提交时发现数据的当前版本号与拿到不同,则认为数据是过期数据,则不能进行提交,回滚数据。
结论:
如果系统并发量不大且不允许脏读,可以使用悲观锁解决并发问题。
如果系统并发量很大的话,悲观锁会带来很大的性能问题,所以一般采用乐观锁。
如果系统读比较多,写比较少,也应该使用乐观锁,提高吞吐量。

15.什么是死锁?如何解决oracle中死锁?

造成死锁的原因是多个线程或进程对同一个资源的争抢或依赖,某个线程获得了锁并没有提交或回滚事务,导致其他线程不能进行操作,一直处于等待状态。表级锁不能操作表,行级锁不能操作行。
解决方法:
1)查询出session会话:
select l.session_id sid,
s.serial#,
l.locked_mode,
l.oracle_username,
s.user#,
l.os_user_name,
s.machine,
s.terminal,
a.sql_text,
a.action
from v s q l a r e a a , v sqlarea a, v session s, v$locked_object l
where l.session_id = s.sid
and s.prev_sql_addr = a.address
order by sid, s.serial#;
2)杀掉会话:
alter system kill session ‘SID,serial#’;

16.DML、DDL、DCL?

1)DML 数据操纵语言,如select、insert、update、delete
2)DDL 数据定义语言,如create、drop
3)DCL 数据控制语言,如commit、rollback、grant、invoke

17.什么是索引?索引的作用?

使用索引的目的,快速访问表中的数据块。在oracle数据库中,存储的每一行数据都有一个rowId来标识。当数据库中存在大量数据时,意味着有大量的rowId,想要快速定位一个rowId,即一行数据,就需要使用索引对象。
当对oracle表执行指定条件的 查询时,常规方法是将所有的记录取出来,然后把每一条记录与查询条件对比,最后返回满足条件的记录。这样不仅耗费时间并且耗费资源。当有了索引之后,只需要在索引中找到(使用算法快速查找)符合查询条件的索引字段值,就可以通过保存在索引中的rowId快速找到表中对应的记录。

18.索引的类型及创建?

在创建索引时,oracle首先将要创建索引的字段进行排序,然后将排序后的字段值和对应记录的rowId存储在索引段中,查询时根据指定条件查询满足的列对应的rowId,再根据rowId提取数据行。
索引类型:
1)B树(bTree)索引
结构:
bTree索引是oracle最常用的索引类型(也是默认类型),是以B树结构组织并存放索引数据。默认情况下B树索引中的数据是以升序方式排列的。B树索引是由根块、分支块、叶块组成,每个节点(叶块)都是数据块。叶子数据块是升序排序的,从左向右递增;在根块和分支块中存放的是索引的范围。
适用:
不能包含or操作符的查询,适合高基数的列(唯一值多)。
创建:
create index emp_dept_index on emp(dept_no) tablespace users;
2)位图(bitmap)索引
结构:
bittree索引的每一个bit对应一个rowId,它的值是0或是1,如果是1,表示bit对应的rowId有值(满足条件)。
适用:
可选结果不多的情况,当需创建索引列包含的值太少时,如针对性别创建索引,取值只有“男”或“女”,如果使用BTree树取出的值仍然很多,失去了索引的意义。适合or操作符的查询。
创建:
create bitmap index emp_gender_index on emp(gender) tablesapce users;
3)反向键索引
结构:
在单调递增的列上使用 B 树索引时,若用户对表中数据做了删除操作,将导致对某一边的叶子节点的大量占用。 Oracle 提供另一种索引机制,及反向键索引,它可以将添加的数据随机分散到索引中。反向键索引是一种特殊的 B 树索引,在顺序递增数列上建立索引非常有用。反向键索引在原理和存储结构方面和 B 树索引类似。当用户插入记录时,将列值进行反向操作后进行索引,此时数据不在是递增的,所以新数据在值的范围上分布通常比原来的有序树更均匀,能高效的利用好并行运算。
适用:
适合单调递增的列。
创建:
create index emp_sal_index on emp(sal) reverse tablesapce users;
4)基于函数的索引
结构:
bTree树结构。
适用:
具有函数转换查询的列。例如:用户在使用数据库时,最常遇到的问题是大小写字符敏感。例如在 emp 表中 Job 字段有 MANAGER 的记录,当用户使用小写搜索时则无法找到该记录,只能通过函数 upper 对应进行转换,在使用转换后的数据进行检查。但是这样查询即便 job 列有普通索引, Oracle 也会执行全表搜索,并为遇到的各个行计算 upper 函数。这种情况可以使用基于函数的索引,通常只是常规 B 树索引,但是它存放的数据是由表中数据应用函数后得到的,而不是直接存放表中的数据本身。
创建:
create index emp_job_index on emp(lower (job)) tablespace users;

19.使用索引的原则及注意事项?

原则:
1)索引字段建议建立not null 约束;
2)经常与其它表建立连接的表,在连接字段上应该建立索引;
3)索引应该建立在where子句频繁引用、排序以及分组的列上,特别是大表字段,如果选择的列不合适将无法提高查询速度;
4)可选择性高(取值范围较大)的字段,应该建立索引;
5)可选择性高的关键字 ,应该建立索引;
6)可选择性低的关键字,但数据的值分布差异很大时,选择性数据比较少时仍然可 以利用索引提高效率;
7)将表和索引部署到相同的表空间,可以简化表空间的管理;部署到不同的表空间,可以提高访问性能(oracle能够并行读取不同硬盘的数据);
注意事项:
1)频繁DML操作的表,不要建立太多的索引;
2)频繁修改的列不要建立索引;
3)在使用LIKE关键字进行查询的查询语句中,如果匹配字符串的第一个字符为"%",索引不会起作用,只有"%"不在第一个位置,索引才会起作用;
4)多个字段创建索引,对于多列索引,只有查询条件中使用了这些字段中第一个字段时,索引才会被使用;
5)查询语句的查询条件中只有OR关键字,且OR前后两个条件都是索引时,查询才会使用索引,否则,查询将不使用索引;

20.索引的优缺点?

优点:
1)大大加快数据库的检索速度,这也是创建索引的主要原因;
2)加速表与表之间的连接,特别是在实现数据的参照完整性方面特别有意义;
3)在使用分组和排序子句进行数据检索时,可以显著减少查询中分组和排序的时间;
缺点:
1)索引不能创建在视图上;
2)创建和维护索引需要耗费时间,这种时间随着数据量的增加而增加;
3)索引需要占用物理空间,如果要建立聚簇索引,那么需要的空间就会更大;
4)当对表中的数据进行增加、修改、删除时,索引也要动态的维护;

21.什么是视图?作用?创建?

简介:
视图(view)也称虚表,不占物理空间,视图只是逻辑定义,每次使用的时候只是重新执行sql语句。视图是从一个或多个数据表中获得的,用于产生视图的表叫做该视图的基表,视图也可从其它视图中产生。
作用:
1)提供各种数据表现形式,可以使用各种不同的方式将基表的数据展现在用户面前,以符合用户的使用习惯(主要手段:使用别名)。
2)隐藏数据的逻辑复杂性并简化查询语句,将多表查询语句创建为一个视图,用户就可以对这个视图进行简单查询获得结果,这样就隐藏了复杂的逻辑简化了sql语句;
3)提供某些安全性保证,即可以让不同的用户看见不同的列,而不允许访问那些敏感的列;
4)简化用户权限管理,可以将视图的权限授予用户,而不必将某表中某列的权限授予用户;
创建:
create or replace [force] view view_name (column1, column2, …)
as
select …
[with read only]; 此参数表示创建的视图只能用于查询数据,不能用于修改数据。
查询出的数据列必须要与视图中定义的列相对应(数量一致)

22.视图与表的区别和联系?

1)视图是从一个或多个基本表中导出的表,给用户使用的“专用表”,是已经预编译好的sql语句,而表不是;
2)视图没有实际的物理记录,不占用物理空间,而表相反;
3)视图是查看表内容的窗口,视图不可以给用户接触表,似的用户不知道表结构,具有更大的安全性;
4)视图只是逻辑概念,只能由创建的语句来修改;
5)视图的建立和删除只影响视图本身,不影响对应的基本表;

23.rowid和rownum。

1)rowid和rownum都是虚列;
2)rowid是物理地址,表示记录在表空间的唯一记录id,用于定义oracle中具体数据的物理存储位置,rownum则是sql的输出结果排序(查到结果集之后才加上去的一个列,强调:先有结果集);
注意,rownum不能以任何基表的名称作为前缀。
oracle使用rownum进行分页:
select * from (select rownum as rn, t.* from table_name t < 20) where rn > 10

24.数据库优化?

数据库性能关键因素在I/O,操作内存是快速的,读写磁盘是很慢的,优化是数据库的关键是减少磁盘I/O。
物理优化:
1)数据库运行环境(网络、硬件等);
2)使用合适的优化器;
3)合理配置数据库实例参数;
4)建立合适的索引(减少I/O);
5)将索引数据和表数据分开在不同的表空间上(降低I/O冲突);
6)建立表分区,将数据存储的不同的分区上(空间换取时间,减少I/O);
逻辑优化:
1)对表进行逻辑分割,如手机号码表,可以根据手机尾数分为10个表;
2)sql语句使用占位符,oracle解析后会放到共享池中;
3)尽量不使用*号,要转化为具体的列需要查数据字典,比较耗时;
4)from子句规则,oracle中多表查询是根据from子句从右到左的顺序进行的(默认优化器),那么最好最右边的表(也就是基础表)选择数据较少的表,这样排序更快速。如果有link表(多对多中间表),那么最好将link表作为基础表,oracle会自动优化。
5)where子句规则,oracle中where子句中的条件是从右往左处理的,表之间的连接最好写在其它条件之前,能过滤掉大量数据的条件最好写在where子句的末尾;
6)使用exits、not exits替代in、not in,在子查询中,in子句将执行一个内部的排序与合并,对子查询表执行了全表遍历;
7)合理使用事务,合理设置事务隔离性,尽量批量处理,降低事务操作次数;
8)将字段很多的表分解为多个表;
9)对于经常联合查询的表,增加中间表来提高查询效率;

持续更新中…

猜你喜欢

转载自blog.csdn.net/weixin_42671172/article/details/106849808