Oracle 小知识点,面试官常问

一、 count(1)与count(*),count(列明)区别

执行效果:


1.  count(1) and count(*)

当表的数据量大些时,对表作分析之后,使用count(1)还要比使用count(*)用时多了! 
从执行计划来看,count(1)和count(*)的效果是一样的。 但是在表做过分析之后,count(1)会比count(*)的用时少些(1w以内数据量),不过差不了多少。 
 
如果count(1)是聚索引,id,那肯定是count(1)快。但是差的很小的。 
因为count(*),自动会优化指定到那一个字段。所以没必要去count(1),用count(*),sql会帮你完成优化的 因此:count(1)和count(*)基本没有差别! 
 
2. count(1) and count(字段)
两者的主要区别是
(1) count(1) 会统计表中的所有的记录数,包含字段为null 的记录。
(2) count(字段) 会统计该字段在表中出现的次数,忽略字段为null 的情况。即不统计字段为null 的记录。 
转自:http://www.cnblogs.com/Dhouse/p/6734837.html


3.count(*) 和 count(1)和count(列名)区别  

执行效果上:  
count(*)包括了所有的列,相当于行数,在统计结果的时候,不会忽略列值为NULL  
count(1)包括了忽略所有列,用1代表代码行,在统计结果的时候,不会忽略列值为NULL  
count(列名)只包括列名那一列,在统计结果的时候,会忽略列值为空(这里的空不是只空字符串或者0,而是表示null)的计数,即某个字段值为NULL时,不统计。

执行效率上:  
列名为主键,count(列名)会比count(1)快  
列名不为主键,count(1)会比count(列名)快  
如果表多个列并且没有主键,则 count(1) 的执行效率优于 count(*)  
如果有主键,则 select count(主键)的执行效率是最优的  
如果表只有一个字段,则 select count(*)最优。

 

==========================================================

二、 in 和 exists的区别

in是把外表和内表作hash连接,而exists是对外表作loop循环,每次loop循环再对内表进行查询,一直以来认为exists比in效率高的说法是不准确的。如果查询的两个表大小相当,那么用in和exists差别不大;如果两个表中一个较小一个较大,则子查询表大的用exists,子查询表小的用in;

例如:表A(小表),表B(大表)

select * from A where cc in(select cc from B)  -->效率低,用到了A表上cc列的索引;

select * from A where exists(select cc from B where cc=A.cc)  -->效率高,用到了B表上cc列的索引。

相反的:

select * from B where cc in(select cc from A)  -->效率高,用到了B表上cc列的索引

select * from B where exists(select cc from A where cc=B.cc)  -->效率低,用到了A表上cc列的索引。

 

2、not in 和not exists

not in 逻辑上不完全等同于not exists,如果你误用了not in,小心你的程序存在致命的BUG,请看下面的例子:

复制代码

create table #t1(c1 int,c2 int);

create table #t2(c1 int,c2 int);

insert into #t1 values(1,2);

insert into #t1 values(1,3);

insert into #t2 values(1,2);

insert into #t2 values(1,null);

 

select * from #t1 where c2 not in(select c2 from #t2);  -->执行结果:无

select * from #t1 where not exists(select 1 from #t2 where #t2.c2=#t1.c2)  -->执行结果:1  3

复制代码

正如所看到的,not in出现了不期望的结果集,存在逻辑错误。如果看一下上述两个select 语句的执行计划,也会不同,后者使用了hash_aj,所以,请尽量不要使用not in(它会调用子查询),而尽量使用not exists(它会调用关联子查询)。如果子查询中返回的任意一条记录含有空值,则查询将不返回任何记录。如果子查询字段有非空限制,这时可以使用not in,并且可以通过提示让它用hasg_aj或merge_aj连接。

如果查询语句使用了not in,那么对内外表都进行全表扫描,没有用到索引;而not exists的子查询依然能用到表上的索引。所以无论哪个表大,用not exists都比not in 要快。

 

3、in 与 = 的区别

select name from student where name in('zhang','wang','zhao');

select name from student where name='zhang' or name='wang' or name='zhao'

的结果是相同的。

 

===========================================

三、表的分区类型说明

A.创建range分区,一般用于日期化处理,range分区可以很好的管理基于日期来分区的数据 
创建一个新用户ls 
SYS@LEO> create user ls identified by ls; 
SYS@LEO> grant dba to ls; 
SYS@LEO> conn ls/ls 
创建样本数据表 
create table liusheng (orderid number(10),name varchar2(10),ls_date date); 
insert into liusheng values (1,'ls1',to_date('1981-01-02','yyyy-mm-dd')); 
insert into liusheng values (1,'ls2',to_date('1998-01-03','yyyy-mm-dd')); 
insert into liusheng values (1,'ls3',to_date('1999-01-04','yyyy-mm-dd')); 
insert into liusheng values (1,'ls4',to_date('2000-01-05','yyyy-mm-dd')); 
insert into liusheng values (1,'ls5',to_date('2000-01-06','yyyy-mm-dd')); 
insert into liusheng values (1,'ls6',to_date('2001-01-07','yyyy-mm-dd')); 
insert into liusheng values (1,'ls7',to_date('2001-01-08','yyyy-mm-dd')); 
insert into liusheng values (1,'ls8',to_date('2002-01-09','yyyy-mm-dd')); 
insert into liusheng values (1,'ls9',to_date('2002-01-10','yyyy-mm-dd')); 
insert into liusheng values (1,'ls10',to_date('2011-01-11','yyyy-mm-dd')); 
创建range分区表 
create table liusheng_part 
partition by range (ls_date) 

partition liusheng_part_1999_1 values less than (to_date('1999-01-01','yyyy-mm-dd')) , 
partition liusheng_part_2000_1 values less than (to_date('2000-01-01','yyyy-mm-dd')) , 
partition liusheng_part_2001_1 values less than (to_date('2001-01-01','yyyy-mm-dd')) , 
partition liusheng_part_2002_1 values less than (to_date('2002-01-01','yyyy-mm-dd')) , 
partition liusheng_part_2003_1 values less than (to_date('2003-01-01','yyyy-mm-dd')) , 
partition other values less than (maxvalue) 

as select * from liusheng; 
查看分区 
select * from liusheng_part partition (liusheng_part_1999_1); 
select * from liusheng_part partition (liusheng_part_2000_1); 
select * from liusheng_part partition (liusheng_part_2001_1); 
select * from liusheng_part partition (liusheng_part_2002_1); 
select * from liusheng_part partition (liusheng_part_2003_1); 
select * from liusheng_part partition (other); 


B.创建hash分区,利用hash函数打散某列使数据均匀分布,一般用于均衡I/O,缺点数据不容易管理,哈希分区不能DROP、SPLIT 以及MERGE分区 
我们创建了拥有10个分区的哈希分区表“LIUSHENG_HASH” 
LS@LEO> create table liusheng_hash partition by hash(object_id) partitions 10 as select * from dba_objects; 
hash分区所占用的区个数,看每个分区占用的个数都差不多,说明数据还是比较均匀分布的 
缺点:hash列上数值不能有太多的重复值,否则会导致数据分布不均匀 
select partition_name,count(*) from user_extents where segment_name='LIUSHENG_HASH' group by partition_name; 
PARTITION_NAME                   COUNT(*) 
------------------------------ ---------- 
SYS_P27                                 3 
SYS_P26                                 3 
SYS_P22                                 2 
SYS_P28                                 3 
SYS_P29                                 2 
SYS_P21                                 2 
SYS_P23                                 3 
SYS_P25                                 3 
SYS_P30                                 2 
SYS_P24                                 3 
select count(*) from liusheng_hash; 

COUNT(*) 
---------- 
       9860 


C.创建list分区,一般用于数据可枚举,有限个值,可以考虑列表分区,例如国家名字,按州来分区 
创建list分区表,我们按国家来分别存放在不同的州,每个州是一个分区 
create table liusheng_list 
(city_id NUMBER(5), 
city_name VARCHAR2(30), 
city_state VARCHAR2(20), 
city_amount NUMBER(10) 

partition by list (city_name) 

partition  asia VALUES('china','japan'), 
partition  europe VALUES ('germany','italy'), 
partition  africa VALUES('libya','brazil'), 
partition  other  VALUES(DEFAULT)              --默认分区 
); 
插入数据 
insert into liusheng_list values(1,'china','asia',100); 
insert into liusheng_list values(2,'germany','europe',101); 
insert into liusheng_list values(3,'libya','africa',102); 
insert into liusheng_list values(4,'liusheng_city','other',103); 
查看数据 
LS@LEO> select * from liusheng_list; 

   CITY_ID COUNTRY_NAME                   STATE                CITY_AMOUNT 
---------- ------------------------------ -------------------- ----------- 
          1 china                                               asia                         100 
          2 germany                                      europe                       101 
          3 libya                                                 africa                       102 
          4 liusheng_city                                 other                        103 

补充:分区之优势 
分区技术实质可以把数据分摊到不同的物理位置,增加I/O负载,提高检索效率。 
可用性:分区表可以跨越表空间,而普通表则不然,好处就是如果表的一个分区损坏,其他分区不会受到影响我们只需要修复损坏的分区即可

 

=============================================

四、sqlloader 的参数

errors -- 允许的错误记录数,可以用他来控制一条记录都不能错

rows -- 多少条记录提交一次,默认为 64 skip -- 跳过的行数,比如导出的数据文件前面几行是表头或其他描述

Fields terminated by ‘|’  -- 数据中每行记录用 "," 分隔

Optionally enclosed by ‘“’  -- 数据中每个字段用 '"' 框起,比如字段中有 "," 分隔符时 

 

======================================

五、触发器的触发类型:

 (如果一条insert语句在一个表中插入500行, 那么这个表的

语句级触发器只执行一次, 而

行级触发器要执行500次)

可以按字面意思理解: 行级触发器针对行, 语句级触发器针对语句(一个语句可以包含多行).

 

触发器是有一个事件隐藏式调用的,它的作用是监听对数据库对象的操作,主要是通过事件来触发而被执行的。它可以强化约束,来维护数据的完整性和一致性,也可以实现级联运算。

 

=============================================

 

你可能感兴趣的:(自学知识点总结)