Oracle 基礎篇 --- 索引

##第四. 索引sql

###4.1 定義bash

索引是與表關聯的可選結構。經過建立索引可提升數據更新和檢索的性能。Oracle 索引提供到數據行的直接訪問路徑。服務器

能夠對錶的一個或多個列建立索引。建立索引後,Oracle 服務器會自動維護和使用索引。表數據的更新(如添加新行、更新行或刪除行)會自動傳播到全部相關的索引,這些對用戶來講是徹底透明的。ide

索引還能夠提升實施主鍵和惟一鍵約束條件時的性能。若是沒有索引,則每次對錶執行DML 操做時都會掃描整個表(全表掃描)。性能

此處輸入圖片的描述

###4.2 類型ui

有多種類型的索引結構,能夠根據須要使用。最經常使用的兩種 類型是:code

####4.2.1 B 樹索引orm

此處輸入圖片的描述

默認的索引類型; 採用平衡樹的形式. B 樹索引的鍵值存儲在平衡樹(B 樹)中,這樣能夠快速執行二進制搜索。排序


B 樹索引的結構索引

索引的頂層爲根,它包含指向索引中下一層次的條目。下一層次爲分支塊,它又指向位於索引中下一層次的塊。最底層是葉節點,它包含指向錶行的索引條目。葉塊是雙向關聯的,這便於按鍵值升序或降序掃描索引。


索引葉條目的格式

  • 條目頭:存儲列數和鎖定信息
  • 鍵列長度/值對:用於定義鍵中的列大小,後面跟隨列值(此類長度/值對的數目就是索引中的最大列數)。
  • ROWID:包含鍵值的行的行ID

索引葉條目的特性

在非分區表的B 樹索引中:

  • 當多個行具備相同的鍵值時,若是不壓縮索引,鍵值會出現重複
  • 當某行包含的全部鍵列爲NULL 時,該行沒有對應的索引條目。所以,當WHERE 子句指定了NULL 時,將始終執行全表掃描
  • 由於全部行屬於同一個段,因此要使用受限的ROWID 指向錶行

對索引執行DML 操做的效果

對錶執行DML 操做時,Oracle 服務器會維護全部索引。下面說明對索引執行DML 命令產生的效果:

  • 執行插入操做致使在相應塊中插入索引條目。
  • 刪除一行只致使對索引條目進行邏輯刪除。已刪除行所佔用的空間不可供後面新的葉條目使用。
  • 更新鍵列致使對索引進行邏輯刪除和插入。PCTFREE設置對索引沒有影響,但建立時除外。即便索引塊的空間少於PCTFREE指定的空間,也能夠向索引塊添加新條目。

###4.3 建立

#建立索引
create index emp3_name_ix on
emp3(emp3_name);

#查看索引的信息
select index_name, index_type, table_name, table_type, uniqueness, status
from user_indexes
where table_name = 'EMP3';

INDEX_NAME      INDEX_TYPE      TABLE_NAME      TABLE_TYPE  UNIQUENES STATUS
--------------- --------------- --------------- ----------- --------- --------
EMP3_ID_PK      NORMAL          EMP3            TABLE       UNIQUE    VALID
EMP3_NAME_IX    NORMAL          EMP3            TABLE       NONUNIQUE VALID

#查看索引對應的列
SQL> select * from user_ind_columns where table_name = 'EMP3';

INDEX_NAME      TABLE_NAME      COLUMN_NAME     COLUMN_POSITION COLUMN_LENGTH CHAR_LENGTH DESC
--------------- --------------- --------------- --------------- ------------- ----------- ----
EMP3_ID_PK      EMP3            EMP3_ID                       1            22           0 ASC
EMP3_NAME_IX    EMP3            EMP3_NAME                     1            10          10 ASC


SQL> select * from emp3 where emp3_name = 'qa1';

   EMP3_ID EMP3_NAME      DEP_ID
---------- ---------- ----------
         2 qa1                 2


Execution Plan
----------------------------------------------------------
Plan hash value: 215206995

--------------------------------------------------------------------------------------------
| Id  | Operation                   | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |              |     1 |    33 |     1   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| EMP3         |     1 |    33 |     1   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | EMP3_NAME_IX |     1 |       |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("EMP3_NAME"='qa1')


Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          3  consistent gets
          0  physical reads
          0  redo size
        675  bytes sent via SQL*Net to client
        524  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

###4.4 決定使用全表掃描仍是使用索引

在大多數狀況下,全表掃描可能會致使更多的物理磁盤輸入輸出,可是全表掃描有時又可能會由於高度並行化的存在而執行的更快。

索引範圍掃描的整體原則是:

  • 對於原始排序的表僅讀取少於表記錄數40%的查詢應該使用索引範圍掃描。 反之,讀取記錄數目多於表記錄數的40%的查詢應該使用全表掃描。
  • 對於未排序的表僅讀取少於表記錄數7%的查詢應該使用索引範圍掃描。 反之,讀取記錄數目多於表記錄數的7%的查詢應該使用全表掃描。
###決定使用全表掃描仍是使用索引
		 
SQL> select index_name, index_type, table_name, uniqueness, status from user_indexes where table_name = 'EMP3';

INDEX_NAME      INDEX_TYPE TABLE_NAME      UNIQUENESS STATUS
--------------- ---------- --------------- ---------- --------
EMP3_ID_PK      NORMAL     EMP3            UNIQUE     VALID
EMP3_NAME_IX    NORMAL     EMP3            NONUNIQUE  VALID

SQL> select count(*) from emp3;

  COUNT(*)
----------
       19

#雖然有索引,可是此時是全表掃描
SQL> select * from emp3 where emp3_name = 'qa8';

   EMP3_ID EMP3_NAME      DEP_ID
---------- ---------- ----------
        16 qa8                 2


Execution Plan
----------------------------------------------------------
Plan hash value: 2425169977

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |    11 |     2   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| EMP3 |     1 |    11 |     2   (0)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("EMP3_NAME"='qa8')


Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          3  consistent gets
          0  physical reads
          0  redo size
        671  bytes sent via SQL*Net to client
        524  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

#往emp3表添加數據
[root@hzvscmdb sql]# more insert_data.sql
#!/bin/bash
i=$1;

while [ $i -le $2 ]
do
sqlplus hr/CCM%lab123@tony1521 <<EOF
insert into emp3 values($i,'$3',$4);
commit;
quit;
EOF
let i=i+1
done

echo "inset into emp3 table"

[root@hzvscmdb sql]# ./insert_data.sql 90 100 dev 1

SQL> select max(emp3_id) from emp3;

MAX(EMP3_ID)
------------
      100000

SQL> analyze table emp3 estimate statistics;

Table analyzed.

SQL> select blocks, empty_blocks, num_rows from user_tables where table_name = 'EMP3';

    BLOCKS EMPTY_BLOCKS   NUM_ROWS
---------- ------------ ----------
       374           10     101081

#查看一條數據
SQL> select * from emp3 where emp3_name = 'qa33333';

   EMP3_ID EMP3_NAME      DEP_ID
---------- ---------- ----------
     33333 qa33333             2


Execution Plan
----------------------------------------------------------
Plan hash value: 215206995

--------------------------------------------------------------------------------------------
| Id  | Operation                   | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |              |     1 |    14 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| EMP3         |     1 |    14 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | EMP3_NAME_IX |     1 |       |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("EMP3_NAME"='qa33333')


Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
          4  consistent gets
          0  physical reads
          0  redo size
        681  bytes sent via SQL*Net to client
        524  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed


#不加條件的查詢,索引掃描
SQL> select count(*) from emp3;

  COUNT(*)
----------
    100000


Execution Plan
----------------------------------------------------------
Plan hash value: 2418373429

----------------------------------------------------------------------------
| Id  | Operation             | Name       | Rows  | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |            |     1 |    70   (2)| 00:00:01 |
|   1 |  SORT AGGREGATE       |            |     1 |            |          |
|   2 |   INDEX FAST FULL SCAN| EMP3_ID_PK |   101K|    70   (2)| 00:00:01 |
----------------------------------------------------------------------------


Statistics
----------------------------------------------------------
          2  recursive calls
          2  db block gets
        262  consistent gets
         37  physical reads
        176  redo size
        526  bytes sent via SQL*Net to client
        524  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

#沒有建立索引的,查詢全表掃描
SQL> select count(*) from emp3 where dep_id = 2;

  COUNT(*)
----------
     85726


Execution Plan
----------------------------------------------------------
Plan hash value: 1396384608

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 |     2 |   104   (1)| 00:00:02 |
|   1 |  SORT AGGREGATE    |      |     1 |     2 |            |          |
|*  2 |   TABLE ACCESS FULL| EMP3 | 50541 |    98K|   104   (1)| 00:00:02 |
---------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter("DEP_ID"=2)


Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
        373  consistent gets
          0  physical reads
          0  redo size
        528  bytes sent via SQL*Net to client
        524  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed


SQL> select count(*) from emp3 where emp3_name like 'qa%';

  COUNT(*)
----------
     85726


Execution Plan
----------------------------------------------------------
Plan hash value: 3884997069

----------------------------------------------------------------------------------
| Id  | Operation         | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |              |     1 |     8 |     2   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE   |              |     1 |     8 |            |          |
|*  2 |   INDEX RANGE SCAN| EMP3_NAME_IX |     7 |    56 |     2   (0)| 00:00:01 |
----------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("EMP3_NAME" LIKE 'qa%')
       filter("EMP3_NAME" LIKE 'qa%')


Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
        395  consistent gets
          0  physical reads
          0  redo size
        528  bytes sent via SQL*Net to client
        524  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed
相關文章
相關標籤/搜索