Oracle索引知識學習筆記

@session

1、Oracle索引簡介

在看《收穫,不止SQL優化》一書,並根據書中例子進行實踐,整理成筆記數據結構

1.1 索引分類

Oracle索引分爲BTree索引、位圖索引、反向索引、函數索引、全文索引等等。oracle

1.2 索引數據結構

Oracle索引中最經常使用的是BTree索引,因此就以BTree索引爲例,講一下BTree索引,BTree索引數據結構是一種二叉樹的結構,索引由根塊(Root)、莖塊(Branch)、葉子塊(Leaf)組成,其中葉子塊主要存儲索引列具體值(Key Column Value)以及能定位到數據塊具體位置的Rowid,莖塊和根塊主要保存對應下級對應索引app

在這裏插入圖片描述

1.3 索引特性

索引特性:ide

  • 索引自己是有序的
  • 索引自己能存儲列值

1.4 索引使用注意要點

  • (1)、僅等值無範圍查詢時,組合的順序不影晌性能
drop table t purge; 
create table t as select * from dba objects;
update t set object_id=rownum ;
commit;
create index idx_id_type on t(object_id, object_type) ; 
create index idx_type_id on t(object_type , object_id) ; 
set autotrace off; 
alter session set statistics_level=all ; 
select /*+index(t idx_id_type)*/ * from t where object_id=20 and object_type='TABLE';
select * from table(dbms_xplan.display cursor(null , null , 'allstats last')); 
select /*+index(t,idx_type id)*/ * from t where object_id=20 and object_type= 'TABLE'; 
select * from table(dbms_xplan.display cursor(null , null , 'allstats last'));
  • (2)、範圍查詢時,組合索引最佳順序通常是將等值查詢的列置前
select /*+index (t, idx_id_type)*/ * from t where object_id>=20 and object_id<2000 and 
object_type='TABLE';

select /*+index (t , idx_type_id) */ * from t where object_id>=20 and object_id<2000 
and object type='TABLE';
  • (3)、Oracle不能同時在索引根的兩段尋找最大值和最小值
set autotrace on
select max(object_id) , min(object_id) from t;

笛卡爾乘積寫法:函數

set autotrace on

select max, min 
from (select max(object_id) max from t ) a , 
(select min(object_id) min from t ) b;
  • (4)、索引最新的數據塊通常是在最右邊

1.五、索引的缺點

  • 熱快競爭:索引最新的數據塊通常在最右邊,而訪問也通常是訪問比較新的數據,因此容易形成熱快競爭
  • 更新新增問題:索引自己是有序的,因此查詢時候很快,可是更新時候就麻煩了,新增更新索引都須要保證排序

1.六、索引失效

索引失效分爲邏輯失效和物理失效性能

  • 邏輯失效
    邏輯失效是由於一些sql語法致使索引失效,好比加了一些函數,而索引列不是函數索引
  • 物理失效
    物理失效是真的失效,好比被設置unusable屬性,分區表的不規範操做也會致使索引失效等等狀況
alter index index_name unusable;

2、索引分類介紹

索引分類:BTree索引、位圖索引、函數索引、反向索引、全文索引測試

2.一、位圖索引

位圖索引:位圖索引儲存的就是比特值優化

環境準備,位圖索引性質適用於count時,效率最高

drop table t purge;
create table t as select * from dba_objects;
update t set object_id = rownum;
commit;

不用索引的狀況:

SQL> set autotrace on
SQL> select count(*) from t;
  COUNT(*)
----------
     72016
執行計劃
----------------------------------------------------------
Plan hash value: 2966233522
-------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Cost (%CPU)| Time     |
-------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 |   288   (1)| 00:00:04 |
|   1 |  SORT AGGREGATE    |      |     1 |            |          |
|   2 |   TABLE ACCESS FULL| T    | 86565 |   288   (1)| 00:00:04 |
-------------------------------------------------------------------
Note
-----
   - dynamic sampling used for this statement (level=2)
統計信息
----------------------------------------------------------
          4  recursive calls
          0  db block gets
       1111  consistent gets
          0  physical reads
          0  redo size
        432  bytes sent via SQL*Net to client
        419  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed
SQL>

建立位圖索引:

create bitmap index idx_bitm_t_status on t(status);

再次查詢,走位圖索引查詢:

SQL> set autotrace on
SQL> select count(*) from t;
  COUNT(*)
----------
     72016
執行計劃
----------------------------------------------------------
Plan hash value: 4272013625
--------------------------------------------------------------------------------
-----------
| Id  | Operation                     | Name              | Rows  | Cost (%CPU)|
 Time     |
--------------------------------------------------------------------------------
-----------
|   0 | SELECT STATEMENT              |                   |     1 |     5   (0)|
 00:00:01 |
|   1 |  SORT AGGREGATE               |                   |     1 |            |
          |
|   2 |   BITMAP CONVERSION COUNT     |                   | 86565 |     5   (0)|
 00:00:01 |
|   3 |    BITMAP INDEX FAST FULL SCAN| IDX_BITM_T_STATUS |       |            |
          |
--------------------------------------------------------------------------------
-----------
Note
-----
   - dynamic sampling used for this statement (level=2)
統計信息
----------------------------------------------------------
          0  recursive calls
          0  db block gets
          6  consistent gets
          0  physical reads
          0  redo size
        432  bytes sent via SQL*Net to client
        419  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed
SQL>

注意要點:

位圖索引更新列容易形成死鎖,因此查詢比較多列才適合建位圖索引,更新比較多的列就儘可能不要建索引

1.二、函數索引

函數索引:就是將一個函數計算的結果存儲在行的列中

環境準備:

drop table t purge;
create table t (id int, status varchar2(2));
insert into t select 1,'N' from dual;
insert into t select rownum ,'Y' from dual connect by rownum <1000;
commit;

不走索引的查詢:

SQL> set autotrace on
SQL> select * from t where (case when status='N' then 'No' end)='No';
        ID STAT
---------- ----
         1 N
執行計劃
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |    16 |     3   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| T    |     1 |    16 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter(CASE "STATUS" WHEN 'N' THEN 'No' END ='No')
Note
-----
   - dynamic sampling used for this statement (level=2)
統計信息
----------------------------------------------------------
          0  recursive calls
          0  db block gets
          8  consistent gets
          0  physical reads
          0  redo size
        486  bytes sent via SQL*Net to client
        419  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed
SQL>

建立函數索引:

create index idx_status on t (case when status ='N' then 'No' end);

走函數索引的查詢:

SQL> select * from t where (case when status='N' then 'No' end)='No';
        ID STAT
---------- ----
         1 N
執行計劃
----------------------------------------------------------
Plan hash value: 3908194542
--------------------------------------------------------------------------------
----------
| Id  | Operation                   | Name       | Rows  | Bytes | Cost (%CPU)|
Time     |
--------------------------------------------------------------------------------
----------
|   0 | SELECT STATEMENT            |            |    10 |   200 |     2   (0)|
00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T          |    10 |   200 |     2   (0)|
00:00:01 |
|*  2 |   INDEX RANGE SCAN          | IDX_STATUS |     4 |       |     1   (0)|
00:00:01 |
--------------------------------------------------------------------------------
----------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access(CASE "STATUS" WHEN 'N' THEN 'No' END ='No')
Note
-----
   - dynamic sampling used for this statement (level=2)
統計信息
----------------------------------------------------------
          0  recursive calls
          0  db block gets
          2  consistent gets
          0  physical reads
          0  redo size
        486  bytes sent via SQL*Net to client
        419  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed
SQL>

注意要點:

自定義函數時要加上deterministic 關鍵字,否則不能創建函數索引

創建一個自定義函數:

create or replace function f_addusl(i int) return int is
begin
  return(i + 1);
end;

嘗試創建函數索引:

create index idx_ljb_test on t(f_addusl(id));

提示:ORA-30553:函數不能肯定

用deterministic 關鍵字,就能夠創建函數索引

create or replace function f_addusl(i int) return int deterministic is
begin
  return(i + 1);
end;

在自定義函數代碼更新時,對應的函數索引也要重建,不然不能用到原來的函數索引

1.三、反向索引

反向索引:反向索引其實也是BTree索引的一種特例,不過在列中字節會反轉的(反向索引是爲了不熱快競爭,好比索引列中存儲的列值是遞增的,好比250101,250102,按照BTree索引的特性,通常是按照順序存儲在索引右邊的,因此容易造成熱快競爭,而反向索引能夠避免這種狀況,由於反向索引是這樣存儲的,好比101052,201052,這樣列值就距離很遠了,避免了熱快競爭)

反向索引不能用到範圍查詢

SQL> set autotrace on
SQL> select * from t where created=sysdate;
未選定行
執行計劃
----------------------------------------------------------
Plan hash value: 913247507
--------------------------------------------------------------------------------
---------------
| Id  | Operation                   | Name            | Rows  | Bytes | Cost (%C
PU)| Time     |
--------------------------------------------------------------------------------
---------------
|   0 | SELECT STATEMENT            |                 |    12 |  2484 |   286
(0)| 00:00:04 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T               |    12 |  2484 |   286
(0)| 00:00:04 |
|*  2 |   INDEX RANGE SCAN          | IDX_REV_CREATED |   346 |       |     1
(0)| 00:00:01 |
--------------------------------------------------------------------------------
---------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("CREATED"=SYSDATE@!)
Note
-----
   - dynamic sampling used for this statement (level=2)
統計信息
----------------------------------------------------------
          0  recursive calls
          0  db block gets
          2  consistent gets
          0  physical reads
          0  redo size
       1191  bytes sent via SQL*Net to client
        408  bytes received via SQL*Net from client
          1  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          0  rows processed
SQL>

範圍查詢,發現不走反向索引查詢

SQL> select * from t where created>= sysdate-10 and created <= sysdate-1;
OWNER
------------------------------------------------------------
OBJECT_NAME
--------------------------------------------------------------------------------
SUBOBJECT_NAME                                                OBJECT_ID
------------------------------------------------------------ ----------
DATA_OBJECT_ID OBJECT_TYPE                            CREATED
-------------- -------------------------------------- --------------
LAST_DDL_TIME  TIMESTAMP                              STATUS         TE GE SE
-------------- -------------------------------------- -------------- -- -- --
 NAMESPACE EDITION_NAME
---------- ------------------------------------------------------------
SYS
ICOL$
                                                                     20
             2 TABLE                                  15-6月 -19
02-4月 -10     2010-04-02:13:18:38                    VALID          N  N  N
         1
SYS
I_USER1
                                                                     46
            46 INDEX                                  14-6月 -19
OWNER
------------------------------------------------------------
OBJECT_NAME
--------------------------------------------------------------------------------
SUBOBJECT_NAME                                                OBJECT_ID
------------------------------------------------------------ ----------
DATA_OBJECT_ID OBJECT_TYPE                            CREATED
-------------- -------------------------------------- --------------
LAST_DDL_TIME  TIMESTAMP                              STATUS         TE GE SE
-------------- -------------------------------------- -------------- -- -- --
 NAMESPACE EDITION_NAME
---------- ------------------------------------------------------------
02-4月 -10     2010-04-02:13:18:38                    VALID          N  N  N
         4
SYS
CON$
                                                                     28
            28 TABLE                                  13-6月 -19
02-4月 -10     2010-04-02:13:18:38                    VALID          N  N  N
         1
SYS
OWNER
------------------------------------------------------------
OBJECT_NAME
--------------------------------------------------------------------------------
SUBOBJECT_NAME                                                OBJECT_ID
------------------------------------------------------------ ----------
DATA_OBJECT_ID OBJECT_TYPE                            CREATED
-------------- -------------------------------------- --------------
LAST_DDL_TIME  TIMESTAMP                              STATUS         TE GE SE
-------------- -------------------------------------- -------------- -- -- --
 NAMESPACE EDITION_NAME
---------- ------------------------------------------------------------
UNDO$
                                                                     15
            15 TABLE                                  12-6月 -19
02-4月 -10     2010-04-02:13:18:38                    VALID          N  N  N
         1
SYS
C_COBJ#
                                                                     29
            29 CLUSTER                                11-6月 -19
02-4月 -10     2010-04-02:13:18:38                    VALID          N  N  N
OWNER
------------------------------------------------------------
OBJECT_NAME
--------------------------------------------------------------------------------
SUBOBJECT_NAME                                                OBJECT_ID
------------------------------------------------------------ ----------
DATA_OBJECT_ID OBJECT_TYPE                            CREATED
-------------- -------------------------------------- --------------
LAST_DDL_TIME  TIMESTAMP                              STATUS         TE GE SE
-------------- -------------------------------------- -------------- -- -- --
 NAMESPACE EDITION_NAME
---------- ------------------------------------------------------------
         5
SYS
I_OBJ#
                                                                      3
             3 INDEX                                  10-6月 -19
02-4月 -10     2010-04-02:13:18:38                    VALID          N  N  N
         4
SYS
PROXY_ROLE_DATA$
OWNER
------------------------------------------------------------
OBJECT_NAME
--------------------------------------------------------------------------------
SUBOBJECT_NAME                                                OBJECT_ID
------------------------------------------------------------ ----------
DATA_OBJECT_ID OBJECT_TYPE                            CREATED
-------------- -------------------------------------- --------------
LAST_DDL_TIME  TIMESTAMP                              STATUS         TE GE SE
-------------- -------------------------------------- -------------- -- -- --
 NAMESPACE EDITION_NAME
---------- ------------------------------------------------------------
                                                                     25
            25 TABLE                                  09-6月 -19
02-4月 -10     2010-04-02:13:18:38                    VALID          N  N  N
         1
SYS
I_IND1
                                                                     41
            41 INDEX                                  08-6月 -19
02-4月 -10     2010-04-02:13:18:38                    VALID          N  N  N
         4
OWNER
------------------------------------------------------------
OBJECT_NAME
--------------------------------------------------------------------------------
SUBOBJECT_NAME                                                OBJECT_ID
------------------------------------------------------------ ----------
DATA_OBJECT_ID OBJECT_TYPE                            CREATED
-------------- -------------------------------------- --------------
LAST_DDL_TIME  TIMESTAMP                              STATUS         TE GE SE
-------------- -------------------------------------- -------------- -- -- --
 NAMESPACE EDITION_NAME
---------- ------------------------------------------------------------
SYS
I_CDEF2
                                                                     54
            54 INDEX                                  07-6月 -19
02-4月 -10     2010-04-02:13:18:38                    VALID          N  N  N
         4
已選擇9行。
執行計劃
----------------------------------------------------------
Plan hash value: 1322348184
---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |    12 |  2484 |   292   (2)| 00:00:04 |
|*  1 |  FILTER            |      |       |       |            |          |
|*  2 |   TABLE ACCESS FULL| T    |    12 |  2484 |   292   (2)| 00:00:04 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter(SYSDATE@!-10<=SYSDATE@!-1)
   2 - filter("CREATED">=SYSDATE@!-10 AND "CREATED"<=SYSDATE@!-1)
Note
-----
   - dynamic sampling used for this statement (level=2)
統計信息
----------------------------------------------------------
          5  recursive calls
          0  db block gets
       1112  consistent gets
          0  physical reads
          0  redo size
       1770  bytes sent via SQL*Net to client
        419  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          9  rows processed
SQL>

1.四、全文索引

全文索引:所謂Oracle全文索引是經過Oracle詞法分析器(lexer)將全部的表意單元term存儲dr$開頭的表裏並存儲term出現的位置、次數、hash值等等信息,Oracle提供了basic_lexer(針對英語)、chinese_vgram_lexer(漢語分析器)、chinese_lexer(新的漢語分析器)。

  • basic_lexer:是一種適用於英文的分析器,根據空格或者標點符號將詞元分離,無論對於中文來講是沒有空格的,因此這種分析器不適合中文
  • chinese_vgram_lexer:這是一種原先專門的中文分析器,支持全部的漢字字符集,好比zhs16gbk單點。這種分析器,分析過程是按字爲單元進行分析的,舉個例子,「索引自己是有序的」,按照這種分析器,會分紅詞元「索」、「索引」、「引本」、「自己」、「身是」、「是有」、「有序」、「序的」、「的」這些詞元,而後你發現像「序的」這些詞在中文中基本是不成立的,不過這種Oracle分析器自己就不認識中文,因此只能所有分析,很明顯效率是很差的
  • chinese_lexer:這是一種新的中文分析器,前面提到chinese_vgram_lexer這種分析器雖然支持全部的中文字符集,可是效率不高,因此chinese_lexer是對其的改進版本,這種分析器認識不少中文詞彙,可以比較快查詢,提升效率,不過這種分析器只能支持utf-8字符集

Oracle的全文索引具體能夠採用通配符查找、模糊匹配、相關分類、近似查找、條件加權和詞意擴充等方法

環境準備

drop table t purge;
create table t as select * from dba_objects where object_name is not null;
update t set object_name ='高興' where rownum<=2;
commit;
select * from t where object_name like '%高興%';

設置詞法分析器

//設置詞法分析器
BEGIN
  ctx_ddl.create_preference ('lexer1', 'chinese_vgram_lexer');
END;

解鎖ctxsys用戶,同時給你的測試帳號(我這裏用scott)受權使用ctx_ddl

//解鎖ctxsys用戶同時受權
grant ctxapp to scott;
alter user ctxsys account unlock;
alter user ctxsys identified by ctxsys;
connect ctxsys/ctxsys;
grant execute on ctx_ddl to scott;
connect scott/11;

創建全文索引

//刪除全文索引
drop index idx_content;
//查看數據文件信息
select * from v$datafile; 
//創建全文索引
CREATE INDEX  idx_content ON t(object_name) indextype is ctxsys.context  parameters('lexer lexer1');

注意要點:更新數據時候記得執行全文索引同步命令,不然將看不到更新數據

exec ctx_ddl.sync_index('idx_content','20M');
相關文章
相關標籤/搜索