Java面试题-数据库索引存储过程游标视图等等

2021年2月19日 21点热度 0条评论 来源: 李布斯·大魔王

目录

存储过程:

    什么是存储过程?它有什么优点?

    oracle的存储过程和函数有什么区别?

索引:

    什么是索引?它有什么优点?

    索引有什么副作用吗?

触发器:

    什么是触发器,它有哪些优点?说说你遇到过的常见应用?

    触发器分为事前触发和事后触发的区别。语句级触发和行级触发有何区别?

视图:

    视图是什么?游标是什么?

查询优化:

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

    什么能够提高查询速度?

    操作符优化

    说说你知道的一些关于查询优化的方案?

    谈谈你对SQL海量数据查询优化性能的一些看法?

存储过程:

    什么是存储过程?它有什么优点?

存储过程是一组予编译的SQL语句,它的优点有:

允许模块化程序设计:就是说只需要创建一次过程,以后在程序中就可以调用该过程任意次。

可编程性强、灵活:当对数据库进行复杂操作时(如对多个表进行Update,Insert,Query,Delete时),可将此复杂操作用存储过程封装起来与数据库提供的事务处理结合一起使用。

执行速度更快:如果某操作需要执行大量SQL语句或重复执行,存储过程比SQL语句执行的要快。

 减少网络流量:例如一个需要数百行的SQL代码的操作有一条执行语句完成,不需要在网络中发送数百行代码。

 更好的安全机制:对于没有权限执行存储过程的用户,也可授权他们执行存储过程。

    oracle的存储过程和函数有什么区别?

Oracle中的函数与存储过程的区别: 

    A:函数必须有返回值,而过程没有. 

    B:函数可以单独执行.而过程必须通过execute执行. 

    C:函数可以嵌入到SQL语句中执行.而过程不行. 

    其实我们可以将比较复杂的查询写成函数.然后到存储过程中去调用这些函数. 

Oracle中的函数与存储过程的特点: 

    A. 一般来说,存储过程实现的功能要复杂一点,而函数的实现的功能针对性比较强。 

    B. 对于存储过程来说可以返回参数,而函数只能返回值或者表对象。     

    C.存储过程一般是作为一个独立的部分来执行,而函数可以作为查询语句的一个部分来调用,由于函数可以返回一个表对象,因此它可以在查询语句中位于FROM关键字的后面。

索引:

    什么是索引?它有什么优点?

索引就像书的目录,能加快数据库的查询速度。索引使数据库程序无需扫描整个表,就可以在其中找到所需要的数据,索引包含了一个表中包含值的列表,其中包含了各个值的行所存储的位置,索引可以是单个或一组列,索引提供的表中数据的逻辑位置,合理划分索引能够大大提高数据库性能。

select * from ac where id='543233';

CREATE INDEX mytable_ac_ ON ac (id);

DROP INDEX mytable_ac_id_Code;

--查询索引 show index from ac; select * from ac where id='487026' AND Code='456';

--建立多重的索引 CREATE INDEX mytable_ac_id_Code ON ac (id,Code);

注意到在命名时的习惯了吗?使用"表名_字段1名_字段2名"的方式。

    索引有什么副作用吗?

  1. 索引是有大量数据的时候才建立的,没有大量数据反而会浪费时间,因为索引是使用二叉树建立.
  2. 当一个系统查询比较频繁,而新建,修改等操作比较少时,可以创建索引,这样查询的速度会比以前快很多,同时也带来弊端,就是新建或修改等操作时,比没有索引或没有建立覆盖索引时的要慢。
  3. 索引并不是越多越好,太多索引会占用很多的索引表空间,甚至比存储一条记录更多。

对于需要频繁新增记录的表,最好不要创建索引,没有索引的表,执行insert、append都很快,有了索引以后,会多一个维护索引的操作,一些大表可能导致insert 速度非常慢。

触发器:

    什么是触发器,它有哪些优点?说说你遇到过的常见应用?

答:触发器是一种特殊类型的存储过程,触发器主要通过事件触发而被执行的,

触发器的优点:

①.强化约束,触发器能够提供比CHECK约束。

②.跟踪变化,触发器可以跟踪数据库内的操作,从而不允许未经允许许可的更新和变化。

③.联级运算,比如某个表上的触发器中包含对另一个表的数据操作,而该操作又导致该表上的触发器被触发。

    触发器分为事前触发和事后触发的区别。语句级触发和行级触发有何区别?

事前触发器运行于触发事件发生之前,通常可以获取事件之前和新的字段值

事后触发器运行于触发事件发生之后。

语句级触发器可以在语句执行前或后执行,

行级触发在触发器所影响的每一行触发一次

create trigger tri_insert on student for insert as declare @student_id char(10) select @student_id=s.student_id from student s inner join inserted i on s.student_id=i.student_id if @student_id='0000000001' begin raiserror('不能插入1的学号!',16,8) rollback tran end go

视图:

    视图是什么?游标是什么?

答:视图是一种虚拟表,虚拟表具有和物理表相同的功能,可以对虚拟表进行增改查操作。视图通常是一个或多个表的行或列的子集,视图的结果更容易理解(修改视图对基表不影响),获取数据更容易(相比多表查询更方便),限制数据检索(比如需要隐藏某些行或列),维护更方便。

游标对查询出来的结果集作为一个单元来有效的处理,游标可以定位在结果集的特定行、从结果集的当前位置检索一行或多行、可以对结果集中当前位置进行修改。

@、 怎么优化数据库(在数据百万条记录的数据库中 Oracle)?

使用索引

建立分区,分区索引

使用存储过程

@、如何优化SQL语句

    ①. 对操作符的优化 尽量不采用不利用索引的操作符

    如:in ,not in , is null, is not null,<>等

    ②. 对条件字段的一些优化

     采用函数处理的字段不能利用索引,

     进行了显式或隐式的运算的字段不能进行索引

     条件内包括了多个本表的字段运算时不能进行索引

    ③. 在业务密集的SQL当中WHERE后面的条件顺序影响

    ④. 应用ORACLE的HINT(提示)处理

    ⑤. 查询表顺序的影响 

查询优化:

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

不能。如果返回的行数目较大,使用全表扫描的性能较好。

    什么能够提高查询速度?

索引就是通过事先排好序,从而在查找时可以应用二分查找等高效率的算法。

一般的顺序查找,复杂度为O(n),而二分查找复杂度为O(log2n)。当n很大时,二者的效率相差及其悬殊。

比如123456789,你要找2,首先查中间元素5,大于2,所以直接排除掉5右边的6789 然后在1234里继续二分查找。 每次排除1/2的元素,所以是O(log2n)

举个例子:

表中有一百万条数据,需要在其中寻找一条特定id的数据。如果顺序查找,平均需要查找50万条数据。而用二分法,至多不超过20次就能找到。二者的效率差了2.5万倍!

在一个或者一些字段需要频繁用作查询条件,并且表数据较多的时候,创建索引会明显提高查询速度,因为可由全表扫描改成索引扫描。

(无索引时全表扫描也就是要逐条扫描全部记录,直到找完符合条件的,索引扫描可以直接定位).

(2^20=1024*1024=1048576)

    操作符优化

①.IN 操作符

用IN写出来的SQL的优点是比较容易写及清晰易懂,这比较适合现代软件开发的风格。但是用IN的SQL性能总是比较低的,从Oracle执行的步骤来分析用IN的SQL与不用IN的SQL有以下区别:

ORACLE试图将其转换成多个表的连接,如果转换不成功则先执行IN里面的子查询,再查询外层的表记录,如果转换成功则直接采用多个表的连接方式查询。由此可见用IN的SQL至少多了一个转换的过程。一般的SQL都可以转换成功,但对于含有分组统计等方面的SQL就不能转换了。

推荐方案:在业务密集的SQL当中尽量不采用IN操作符,用EXISTS 方案代替。

②.NOT IN操作符

此操作是强列不推荐使用的,因为它不能应用表的索引。

推荐方案:用NOT EXISTS 方案代替

③.IS NULL 或IS NOT NULL操作(判断字段是否为空)

判断字段是否为空一般是不会应用索引的,因为索引是不索引空值的。

推荐方案:用其它相同功能的操作运算代替,如:a is not null 改为 a>0 或a>’’等。不允许字段为空,而用一个缺省值代替空值,如申请中状态字段不允许为空,缺省为申请。

④.> 及 < 操作符(大于或小于操作符)

大于或小于操作符一般情况下是不用调整的,因为它有索引就会采用索引查找,但有的情况下可以对它进行优化,如一个表有100万记录,一个数值型字段A,30万记录的A=0,30万记录的A=1,39万记录的A=2,1万记录的A=3。那么执行A>2与A>=3的效果就有很大的区别了,因为A>2时ORACLE会先找出为2的记录索引再进行比较,而A>=3时ORACLE则直接找到=3的记录索引。

⑤.LIKE操作符

LIKE操作符可以应用通配符查询,里面的通配符组合可能达到几乎是任意的查询,但是如果用得不好则会产生性能上的问题,如LIKE ‘%5400%’ 这种查询不会引用索引,而LIKE ‘X5400%’则会引用范围索引。

一个实际例子:用YW_YHJBQK表中营业编号后面的户标识号可来查询营业编号 YY_BH LIKE ‘%5400%’ 这个条件会产生全表扫描,如果改成YY_BH LIKE ’X5400%’ OR YY_BH LIKE ’B5400%’ 则会利用YY_BH的索引进行两个范围的查询,性能肯定大大提高。

⑥.UNION操作符

UNION在进行表链接后会筛选掉重复的记录,所以在表链接后会对所产生的结果集进行排序运算,删除重复的记录再返回结果。实际大部分应用中是不会产生重复的记录,最常见的是过程表与历史表UNION。如:

select * from gc_dfys

union

select * from ls_jg_dfys

这个SQL在运行时先取出两个表的结果,再用排序空间进行排序删除重复的记录,最后返回结果集,如果表数据量大的话可能会导致用磁盘进行排序。

推荐方案:采用UNION ALL操作符替代UNION,因为UNION ALL操作只是简单的将两个结果合并后就返回。

select * from gc_dfys

union all

select * from ls_jg_dfys

    说说你知道的一些关于查询优化的方案?

1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。

2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:?

     select id from t where num is null?      可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:?      select id from t where num=0

3.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。

4.应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如:?

     select id from t where num=10 or num=20?      可以这样查询:?      select id from t where num=10?      union all?      select id from t where num=20

5.in 和 not in 也要慎用,否则会导致全表扫描,如:?

     select id from t where num in(1,2,3)?      对于连续的数值,能用 between 就不要用 in 了:?      select id from t where num between 1 and 3

6.下面的查询也将导致全表扫描:?

     select id from t where name like '%abc%'?

     若要提高效率,可以考虑全文检索。

7.如果在 where 子句中使用参数,也会导致全表扫描。因为SQL只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推迟到运行时;它必须在编译时进行选择。然而,如果在编译时建立访问计划,变量的值还是未知的,因而无法作为索引选择的输入项。如下面语句将进行全表扫描:?

     select id from t where num=@num?      可以改为强制查询使用索引:?      select id from t with(index(索引名)) where num=@num

8.应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。如:?

     select id from t where num/2=100?      应改为:?      select id from t where num=100*2

9.应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。如:?

     select id from t where substring(name,1,3)='abc'--name以abc开头的id?      select id from t where datediff(day,createdate,'2005-11-30')=0--‘2005-11-30’生成的id?      应改为:?      select id from t where name like 'abc%'?      select id from t where createdate>='2005-11-30' and createdate<'2005-12-1'

10.不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。

11.在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致。

12.不要写一些没有意义的查询,如需要生成一个空表结构:?

     select col1,col2 into #t from t where 1=0?

     这类代码不会返回任何结果集,但是会消耗系统资源的,应改成这样:?

     create table #t(...)

13.很多时候用 exists 代替 in 是一个好的选择:?

     select num from a where num in(select num from b)?

     用下面的语句替换:?

     select num from a where exists(select 1 from b where num=a.num)

14.并不是所有索引对查询都有效,SQL是根据表中数据来进行查询优化的,当索引列有大量数据重复时,SQL查询可能不会去利用索引,如一表中有字段sex,male、female几乎各一半,那么即使在sex上建了索引也对查询效率起不了作用。

15.索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,因为 insert 或 update 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有必要。

16.应尽可能的避免更新 clustered 索引数据列,因为 clustered 索引数据列的顺序就是表记录的物理存储顺序,一旦该列值改变将导致整个表记录的顺序的调整,会耗费相当大的资源。若应用系统需要频繁更新 clustered 索引数据列,那么需要考虑是否应将该索引建为 clustered 索引。

17.尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。

18.尽可能的使用 varchar/nvarchar 代替 char/nchar ,因为首先变长字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。

19.任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。

20.尽量使用表变量来代替临时表。如果表变量包含大量数据,请注意索引非常有限(只有主键索引)。

21.避免频繁创建和删除临时表,以减少系统表资源的消耗。

22.临时表并不是不可使用,适当地使用它们可以使某些例程更有效,例如,当需要重复引用大型表或常用表中的某个数据集时。但是,对于一次性事件,最好使用导出表。

23.在新建临时表时,如果一次性插入数据量很大,那么可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果数据量不大,为了缓和系统表的资源,应先create table,然后insert。

24.如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先 truncate table ,然后 drop table ,这样可以避免系统表的较长时间锁定。

25.尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该考虑改写。

26.使用基于游标的方法或临时表方法之前,应先寻找基于集的解决方案来解决问题,基于集的方法通常更有效。

27.与临时表一样,游标并不是不可使用。对小型数据集使用 FAST_FORWARD 游标通常要优于其他逐行处理方法,尤其是在必须引用几个表才能获得所需的数据时。在结果集中包括“合计”的例程通常要比使用游标执行的速度快。如果开发时间允许,基于游标的方法和基于集的方法都可以尝试一下,看哪一种方法的效果更好。

28.在所有的存储过程和触发器的开始处设置 SET NOCOUNT ON ,在结束时设置 SET NOCOUNT OFF 。无需在执行存储过程和触发器的每个语句后向客户端发送 DONE_IN_PROC 消息。

29.尽量避免大事务操作,提高系统并发能力。

30.尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。

    谈谈你对SQL海量数据查询优化性能的一些看法?

数据库系统是管理信息系统的核心,基于数据库的联机事务处理(OLTP)以及联机分析处理(OLAP)是银行、企业、政府等部门最为重要的计算机应用之一。

从大多数系统的应用实例来看,查询操作在各种数据库操作中所占据的比重最大,而查询操作所基于的SELECT语句在SQL语句中又是代价最大的语句。举例来说,如果数据的量积累到一定的程度,比如一个银行的账户数据库表信息积累到上百万甚至上千万条记录,全表扫描一次往往需要数十分钟,甚至数小时。如果采用比全表扫描更好的查询策略,往往可以使查询时间降为几分钟,由此可见查询优化技术的重要性。

    原文作者:李布斯·大魔王
    原文地址: https://blog.csdn.net/libusi001/article/details/113857724
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系管理员进行删除。