如何查看某張數據庫表上都有哪些索引(轉)


索引使用簡介

一、        關於索引的知識

要寫出運行效率高的sql,需要對索引的機制有一定了解,下面對索引的基本知識做一介紹。

1、        索引的優點和局限
 索引可以提高查詢的效率,但會降低dml操作的效率。
 所以建立索引時需要權衡。對於dml操作比較頻繁的表,索引的個數不宜太多。

2、        什么樣的列需要建索引?
 經常用於查詢、排序和分組的列(即經常在where、order或group by子句中出現的列)。

3、        主鍵索引和復合索引
 對於一張表的主鍵,系統會自動為其建立索引。
 如果一張表的幾列經常同時作為查詢條件,可為其建立復合索引。

4、        建立索引的語句
create  index  i_staff  on  staff  (empno);
 create  index  i_agent  on  agent  (empno, start_date);

5、        刪除索引的語句
drop  index  I_staff;
 drop  index  I_agent;

6、 查詢索引的語句  法一:利用數據字典
 表一:all_indexes  查看一張表有哪些索引以及索引狀態是否有效
 主要字段: index_name,  table_name,  status
例如:select   index_name,  status  
 from  all_indexes
         where  table_name=’STAFF_INFO’;
       INDEX_NAME        STATUS
       ---------------------       -----------
       I_STAFF             VALID  
             表二:all_ind_columns  查看一張表在哪些字段上建了索引
              主要字段: table_name,  index_name,  column_name,  column_position
例如: select  index_name,  column_name,  column_position
 from  all_ind_columns
          where  table_name=’AGENT’
      INDEX_NAME        COLUMN_NAME     COLUMN_POSITON
       ---------------------       -----------------------      --------------------------
      I_AGENT             EMPNO              1
      I_AGENT             START_DATE         2
由此可見,agent表中有一個復合索引(empno, start_date )
     法二:利用toad工具
toad用戶界面比sql*plus友好,並且功能強大。你可以在toad編輯器中鍵入表名,按F4,便可見到這張表的表結構以及所有索引列等基本信息。

7、        索引的一些特點
1): 不同值較多的列上可建立檢索,不同值少的列上則不要建。比如在雇員表的“性別”列上只有“男”與“女”兩個不同值,因此就沒必要建立索引。如果建立索引不但不會提高查詢效率,反而會嚴重降低更新速度。
2): 如果在索引列上加表達式,則索引不能正常使用
   例如:b1,c1分別是表b,c的索引列
select  *  from  b  where  b1/30< 1000 ;
 select  *  from  c  where  to_char(c1,’YYYYMMDD HH24:MI:SS’) = ‘200203 14:01:01’;
以上都是不正確的寫法
        3): where子句中如果使用in、or、like、!=,均會導致索引不能正常使用
           例如:select  *  from  b  where  b1=30  or  b1=40;
       4): 使用復合索引進行查詢時必須使用前置列
         例如表a上有一個復合索引(c1,c2,c3),則c1為其前置列
         如果用c1或c1+c2或c1+c2+c3為條件進行查詢,則該復合索引可以發揮作用,反之,用c2或c3或c2+c3進行查詢,則該索引不能起作用。


 二. 書寫sql注意事項:

1、        避免給sql語句中引用的索引列添加表達式:
 典型實例:
b1,c1分別是表b,c的索引列:
1)        select  *  from  b  where  b1/30< 1000 ;
 2)        select  *  from  c  where to_char(c1,’YYYYMMDD HH24:MI:SS’) = ‘200203 14:01:01’;
替代方案:
1)        select  *  from  b where  b1 < 30000;
 2)        select * from c  where c1 = to_date(‘20020301 14:01:01’, ‘YYYYMMDD HH24:MI:SS’);
注:在lbs中有兩個重要字段,pol_info中的undwrt_date和prem_info中的payment_date,這兩個日期是帶時分秒的,所以經常有同事用to_char 來查詢某一時間段的數據。
 例如:select  count(*)  from  pol_info  where  to_char(undwrt_date,’YYYYMMDD’)=’20020416’;
       select  count(*)  from  prem_info  where  to_char(undwrt_date,’YYYYMM’)=’200203’;
替代方案:
select  count(*)  from  pol_info  
 where  undwrt_date>=to_date(’20020416’,’YYYYMMDD’)  and
            undwrt_date select  count(*)  from  prem_info  
 where  payment_date>=to_date(’20020301’,’YYYYMMDD’)  and
          payment_date 
 2、        避免在where子句中使用in、or、like、!=
典型實例:
a1是a表上的索引列:
1) select  *  from  a
    where  ( a1 = ‘0’ and ...)  or  (a1 = ‘1’ and ...);
 2) select  count(*)  from  a  where  a1  in  (‘0’,’1’) ;
替代方案:
1)        select  *  from  a  where  a1 = ‘0’  and ...
 union
 select  *  from  a  where  a1 = ‘1’  and ...
 2) select  count(*)  from  a  where  a1 = ‘0’;
   select  count(*)  from  a  where a1 = ‘1’;
    然后做一次加法運算;或者直接用存儲過程來實現;
 小結:
 對字段使用了 ‘in,or,like’ 做條件、對字段使用了不等號 ‘!=’,均會使索引失效;如果不產生大量重復值,可以考慮把子句拆開;拆開的子句中應該包含索引,或者使用union連結符代替。另一種方式是使用存儲過程,它使SQL變得更加靈活和高效。

3、        建立適當的索引
 曾經接過開發的一個統計sql, select …  from  tablea  where  cola=…  and  …
運行效率非常慢,經查tablea數據量巨大,再查all_ind_columns,發現cola是tablea的一個復合索引中的一列,但不是前置列。象這種情況,就需要與開發商量,是否針對cola建一個索引。

4、        like和substr
對於‘like’和‘substr’,其效率並沒有多大分別。但是,當所搜索的值不存在時,使用‘like’的速度明顯大於‘substr’。
 所以:select  *  from  a  where  substr(a1,1,4) = '5378'  可以用like替代
select  *  from  a  where  a1  like  ‘5378%’;

5、 寫where條件時,有索引字段的判斷在前,其它字段的判斷在后;如果where條件中用到復合索引,按照索引列在復合索引中出現的順序來依次寫where條件;

6、使用多表連接時,在from子句中,將記錄數少的表放在后面,可提高執行效率;

7、避免使用not in 
 not  in 是效率極低的寫法,盡量使用minus或外連接加以替代
 典型實例:
1) select col1 from tab1 where col1 not in (select col1 from tab2);
 2) select sum(col2) from tab1 where col1 not in (select col1 from tab2);
替代方案
select col1 from tab1 minus  select col1 from tab2;
     select  sum(a.col2)  from  tab1 a, tab2  b 
 where a.col1=b.col2(+) and b.col1 is null;

8、多表查詢時,如果其中一個表的記錄數量明顯大於其他表,則可以先對此表進行查詢后,再與其他小表進行表連接。
 典型實例:
select  a.plan_code,  b.dno,  c,tno,  sum(a.tot_modal_prem),
 from  prem_info a,  dept_ref b,  plan_type c
 where  substr(a.deptno,1,7) = substr(b.deptno,1,7)
 and a.plan_code = c.plan_code
 group by b.dno,  c.tno,  a.plan_code;
替代方案:
select  b.dno,  c.tno,  a.plan_code,  a.tot_amount
 from  (select  plan_code,  deptno,  sum(tot_modal_prem)  tot_amount
 from  prem_info
 group  by  deptno,  plan_code) a
 dept_ref  b,
 plan_type  c
   where  substr(a.deptno,1,7) = substr(b.deptno,1,7)
        and  a.plan_code = c.plan_code
 group  by  b.dno,  c.tno,  a.plan_code;
小結:
 由於prem_info表的記錄數遠遠大於dept_ref表和plan_type表中的記錄數, 所以首先從prem_info表中查詢需要的記錄,此時記錄數已經被大量縮小,然后再和其他兩個表連接,速度會得到很大改善!

9、查詢數量較大時,使用表連接代替IN,EXISTS,NOT IN,NOT EXISTS等。
 典型實例:
a、使用IN:
select sum(col2) from tab1 where col1 in (select col1 from tab2);
使用EXISTS::
select sum(col2) from tab1 a 
 where exists ( select * from tab2 where col1=a.col1);
 b、使用NOT IN:
select sum(col2) from tab1 where col1 not in (select col1 from tab2);
使用NOT EXISTS:
select sum(col2) from tab1 a 
 where not exists ( select * from tab2 where col1=a.col1);
           替代方案:
a、使用連接:
select sum(a.col2) from tab1 a,tab2 b where a.col1=b.col2;
 b、使用外連接:
select sum(a.col2) from tab1 a,tab2 b 
 where a.col1=b.col2(+) and b.col1 is null;

\•索引是建立在表的一列或多個列上的輔助對象,它有利於快速訪問表的數據。 

•索引由於其內在的結構,它具有某些內在的開銷,這些開銷依賴於為了檢索由索引中ROWID指定的行所訪問的表中的塊數,並且這個開銷可能會超過進行全表掃描的成本。

聚集索引確定表中數據的物理順序。聚集索引類似於電話簿,按姓氏排列數據。由於聚集索引規定數據在表中的物理存儲順序,因此一個表只能包含一個聚集索引。但該索引可以包含多個列(組合索引),就像電話簿按姓氏和名字進行組織一樣。 
  聚集索引對於那些經常要搜索范圍值的列特別有效。使用聚集索引找到包含第一個值的行后,便可以確保包含后續索引值的行在物理相鄰。例如,如果應用程序執行的一個查詢經常檢索某一日期范圍內的記錄,則使用聚集索引可以迅速找到包含開始日期的行,然后檢索表中所有相鄰的行,直到到達結束日期。這樣有助於提高此類查詢的性能。同樣,如果對從表中檢索的數據進行排序時經常要用到某一列,則可以將該表在該列上聚集(物理排序),避免每次查詢該列時都進行排序,從而節省成本。 
  當索引值唯一時,使用聚集索引查找特定的行也很有效率。例如,使用唯一雇員 ID 列 emp_id 查找特定雇員的最快速的方法,是在 emp_id 列上創建聚集索引或 PRIMARY KEY 約束。
 

非聚集索引與聚集索引一樣有 B 樹結構,但是有兩個重大差別: 
  數據行不按非聚集索引鍵的順序排序和存儲。非聚集索引的葉層不包含數據頁。 相反,葉節點包含索引行。每個索引行包含非聚集鍵值以及一個或多個行定位器,這些行定位器指向有該鍵值的數據行(如果索引不唯一,則可能是多行)。 非聚集索引可以在有聚集索引的表、堆集或索引視圖上定義。在 Microsoft&reg; SQL Server™ 2000 中,非聚集索引中的行定位器有兩種形式: 
  如果表是堆集(沒有聚集索引),行定位器就是指向行的指針。該指針用文件標識符 (ID)、頁碼和頁上的行數生成。整個指針稱為行 ID。如果表沒有聚集索引,或者索引在索引視圖上,則行定位器就是行的聚集索引鍵。如果聚集索引不是唯一的索引,SQL Server 2000 將添加在內部生成的值以使重復的鍵唯一。用戶看不到這個值,它用於使非聚集索引內的鍵唯一。SQL Server 通過使用聚集索引鍵搜索聚集索引來檢索數據行,而聚集索引鍵存儲在非聚集索引的葉行內。 由於非聚集索引將聚集索引鍵作為其行指針存儲,因此使聚集索引鍵盡可能小很重要。如果表還有非聚集索引,請不要選擇大的列作為聚集索引的鍵。

關於索引(轉)

索引的三個問題 
   索引( Index )是常見的數Database 的性能。雖然有許多,還是有不少的人對它存在誤解Oracle 8.1.7 OPS on HP N se使用不同的方法后,數據的比較明白事情的關鍵。  據庫對象,它的設置好壞、使用是否資料講索引的用法, DBA 和 Develo,因此針對使用中的常見問題,講三ries ,示例全部是真實數據,讀者不。本文所講基本都是陳詞濫調,但是  得當,極大地影響數據庫應用程序和per 們也經常與它打交道,但筆者發現個問題。此文所有示例所用的數據庫是需要注意具體的數據大小,而應注意在筆者試圖通過實際的例子,來真正讓您
   第一講、索引並非總是最佳選擇                                                               
  如果發現Oracle 在有索引,Oracle 確實會選擇全表掃描  的情況下,沒有使用索引,這並不是(Full Table Scan),而非索引掃描  Oracle 的優化器出錯。在有些情況下(Index Scan)。這些情況通常有:
   1. 表未做statistics, 或  者 statistics 陳舊,導致 Oracle   判斷失誤。 
   2. 根據該表擁有的記錄數和數據塊數,實際上全表掃描要比索引掃描更快。                     
  對第1種情況,最常見的例子,是以下這句sql 語句:                                       
  select count(*) from mytable;                                 
  在未作statistics 之前,它使用全表掃描,statistics 之后,使用的是 INDEX (FAST FULL S得不好,也會導致Oracle 不使用索引。  需要讀取6000多個數據塊(一個數據塊是8k), 做了CAN) ,只需要讀取450個數據塊。但是,statistics 做
   第2種情況就要復雜得多。一般概念上都認為掃描快。為了講清楚這個問題,這里先介紹一下Or:CF(Clustering factor) 和 FF(Filtering fact  索引比表快,比較難以理解什么情況下全表掃描要比索引acle 在評估使用索引的代價(cost)時兩個重要的數據or).
  CF: 所謂 CF, 通俗地講,就是每讀入一個索引塊,要對應讀入多少個數據塊。             
  FF: 所謂 FF, 就是該sql 語句所選擇的結果集,占總的數據量的百分比。             
  大約的計算公式是:FF * (要讀入的數據塊塊數。需要讀入全表掃描需要讀入的數據塊數等  CF + 索引塊個數) ,由此估計出,的數據塊越多,則 cost 越大,Orac於該表的實際數據塊數)  一個查詢, 如果使用某個索引,會需le 也就越可能不選擇使用 index. (
   其核心就是, CF 可能會比實際的數據塊數量建立時,索引中的記錄與表中的記錄有良好的對應對應關系越來越亂,CF 也越來越大。此時需要 DB  大。CF 受到索引中數據的排列方式影響,通常在索引剛關系,CF 都很小;在表經過大量的插入、修改后,這種A 重新建立或者組織該索引。
   如果某個sql 語句以前一直重新整理該索引了。  使用某索引,較長時間后不再使用,  一種可能就是 CF 已經變得太大,需要 
   FF 則是Oracle 根據 stati,最大值是409654,考慮以下sq  stics 所做的估計。比如, mytablesl 語句:  表有32萬行,其主鍵myid的最小值是1
  Select * from mytables where myid>=1; 和 
   Select * from mytables where myid>=400000 
  這兩句看似差不多的 sql 者的 FF 可能只有 1%。如果它實際上,在我們的數據庫上的測  語句,對Oracle 而言,卻有巨大的的CF 大於實際的數據塊數,則Oracl試驗證了我們的預測. 以下是在HP   差別。因為前者的 FF 是100%, 而后e 可能會選擇完全不同的優化方式。而
  
第二講、索引也有好壞                                                                       
   
  索引有 B tree 索引, Bit全稱是Balanced , 其意義是,有一個字段(Single column),Function-based index. 許多de  map 索引, Reverse b tree 索引,從 tree 的 root 到任何一個leaf 也可以有多個字段(Composite),veloper 都傾向於使用單列B 樹索引  等。最常用的是 B tree 索引。 B 的,要經過同樣多的 level. 索引可以只最多32個字段,8I 還支持 。
  
  所謂索引的好壞是指:                                                                      
   
  1,索引不是越多越好。特別是大量從來或者個索引即會降低性能,而且在一個sql 中, Oracl  幾乎不用的索引,對系統只有損害。OLTP系統每表超過5e 從不能使用超過 5個索引。
  
  2,很多時候,單列索引不如復合索引有效率。                                                 
   
  3,用於多表連結的字段,加上索引會很有作用。                                               
   
  那么,在什么情況下單列索所查詢的列,全部都出現在復合使用多個單列索引要快得多。(  引不如復合索引有效率呢?有一種情索引中時,此時由於 Oracle 只需要此時,這種優化方式被稱為 Index o  況是顯而易見的,那就是,當sql 語句查詢索引塊即可獲得所有數據,當然比nly access path)
  
第三講、索引再好,不用也是白搭                                                             
  拋開前面所說的,假設你設不用,那么,需要做的第一件事  置了一個非常好的索引,任何傻瓜都情,是審視你的 sql 語句。  知道應該使用它,但是Oracle 卻偏偏
   Oracle 要使用一個索引,有一些最基本的條件:                                         
  1, where 子句中的這個字段,必須是復合索引的第一個字段;                           
  2, where 子句中的這個字段,不應該參與任何形式的計算                               
  具體來講,假設一個索引是按 f1, f2, f3的= : var2, 則因為 f2 不是索引的第1個字段,無  次序建立的,現在有一個 sql 語句, where 子句是 f2 法使用該索引。
   第2個問題,則在我們之中非常嚴重。以下是從 實際系統上面抓到的幾個例子:                   
  Select jobid from mytabs where isReq='0' and to_date (updatedate) >= to_Date ( '2001-7-18', 'YYYY-MM-DD');
   以上的例子能很容易地進行和 內存資源。  改進。請注意這樣的語句每天都在我  們的系統中運行,消耗我們有限的cpu  
  除了1,2這兩個我們必須牢記於心的原則外,。這里我只講哪些操作或者操作符會顯式(explic  還應盡量熟悉各種操作符對 Oracle 是否使用索引的影響itly)地阻止 Oracle 使用索引。以下是一些基本規則:
   1, 如果 f1 和 f2 是同一個表的兩個字段,則 f1>f2, f1>=f2, f1 
  2, f1 is null, f1 is no  t null, f1 not in, f1 !=, f1 lik  e ‘%pattern%’; 
  3, Not exist                                                                   
  4, 某些情況下,f1 in 也會不用索引;                                               
  對於這些操作,別無辦法,許可以將 in 操作改成 比較操  只有盡量避免。比如,如果發現你的作 + union all。筆者在實踐中發現  sql 中的 in 操作沒有使用索引,也很多時候這很有效。
   但是,Oracle 是否真正使用索引,使用索引,對所寫的復雜的 sql, 在將它寫入應用程序之前Oracle 對該 sql 的解析(plan),可以明確地看是否真正有效,還是必須進行實地的測驗。合理的做法是,先在產品數據庫上做一次explain . explain 會獲得到 Oracle 是如何優化該 sql 的。
   如果經常做 explain, 就會划往往不盡如人意。事實上,將然這已經是題外話了。發現,喜愛寫復雜的 sql 並不是個復雜的 sql 拆開,有時候會極大地好習慣,因為過分復雜的sql 其解析計提高效率,因為能獲得很好的優化。當沒有對name建索引之前,oracle使用全表掃描。時間長短視數據庫參數db_file_multiblock_read_count的設置,一次讀取db_file_multiblock_read_count*db_block_size(db_cache_dize)的數據.
建立索引之后,oracle使用index range scan,一次讀取一條索引。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM