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 ‘“’  -- 數據中每個字段用 '"' 框起,比如字段中有 "," 分隔符時 

 

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

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章