溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

oracle 實現基于函數的索引

發(fā)布時間:2020-06-06 21:29:09 來源:網絡 閱讀:694 作者:lineqi 欄目:關系型數據庫

使用場景:
當一個查詢運行很慢。通過檢查where子句,發(fā)現其中的一列應用了sql lower函數,lower函數
阻止使用該列上現有的索引。你想要創(chuàng)建一個基于函數索引來支持這個查詢,如下

SQL> select index_name,column_name from user_ind_columns where table_name='T1';

INDEX_NAME                COLUMN_NAME
------------------------- ------------------------------
T1_PK                     OBJECT_ID

SQL> set autotrace trace explain;
SQL> select * from t1 where lower(object_name)='i_undo1';

執(zhí)行計劃
----------------------------------------------------------
Plan hash value: 3617692013

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |   908 |   101K|   436   (1)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| T1   |   908 |   101K|   436   (1)| 00:00:01 |
--------------------------------------------------------------------------

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

   1 - filter(LOWER("OBJECT_NAME")='i_undo1')
從以上可以看出即使該表中有索引也沒有使用。

解決方案
1、創(chuàng)建一個基于函數的索引
2、如果使用oracle database 11g或更高版本,創(chuàng)建一個索引虛擬列

下面實現基于函數的索引

創(chuàng)建索引可以通過以下方式來估計索引所使用空間以及所需要分配的空間

SQL> set serveroutput on
SQL> var used_bytes number;
SQL> var allo_bytes number;
SQL> exec dbms_space.create_index_cost('create index t1_object_name on t1(lower(object_name))',:used_bytes,:allo_bytes);
 
PL/SQL procedure successfully completed
used_bytes
---------
2269350
allo_bytes
---------
4194304

SQL>create index idx_lower on t1(lower(object_name)) tablespace index_nocompress;

SQL> select * from t1 where lower(object_name)='i_undo1';

執(zhí)行計劃
----------------------------------------------------------
Plan hash value: 2274688371

-------------------------------------------------------------------------------------------------
| Id  | Operation                           | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                    |           |   908 |   101K|   193   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID BATCHED| T1        |   908 |   101K|   193   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN                  | IDX_LOWER |   363 |       |     3   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------

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

   2 - access(LOWER("OBJECT_NAME")='i_undo1')

注意:不能直接修改一個創(chuàng)建了基于函數索引的列。需要先刪除索引,然后修改列,最后再重建索引。不然會報ora-30556錯誤(在要修改的列上已定義函數索引或位圖聯(lián)接索引)

查看基于函數的索引定義dba/all/user_ind_expressions

SQL> select index_name,column_expression from user_ind_expressions;

INDEX_NAME                COLUMN_EXPRESSION
------------------------- --------------------------------------------------
IDX_LOWER                 LOWER("OBJECT_NAME")

接著實現在虛擬列創(chuàng)建一個索引

使用場景

現在正使用一個基于函數的索引,但想要獲得更好的性能,想將基于函數的索引替換為一個虛擬列,然后在虛擬列上創(chuàng)建索引(需要11g環(huán)境或更高版本)。

SQL>alter table t1 add(lower_object_name generated always as (lower(object_name)) virtual);
SQL>create index idx_lower on t1(lower_object_name) tablespace index_nocompress;


 

 

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI