1. 程式人生 > >oracle like模糊查詢的優化測試

oracle like模糊查詢的優化測試

三種like模糊查詢的優化:
第一種:like 'a%'這種,直接可走索引
第二種:like '%a'這種,需要用reverse反轉函式改寫SQL,再建立函式索引,如下:
  改寫前:
   select * from test where owner like '%SCOTT'
   改寫後:
   select * from test where reverse(owner) like reverse('%SCOTT');
第三種:like '%a%'這種的優化,進行如下測試:

原SQL:
SELECT A0.*
 FROM g.wp A0
 where A0.ptc_str_12TYPEINFOWABCDT like '%中ABCDdddddddd機%';

OS下執行:
export NLS_LANG=AMERICAN_AMERICA.utf8

SQL> set line 1000
SQL> set pagesize 1000
SQL> set autotrace traceonly
SQL> set timing on
SQL> SELECT A0.*
  2   FROM g.wp A0
  3   where A0.ptc_str_12TYPEINFOWABCDT like '%中ABCDdddddddd機%';

4694 rows selected.

Elapsed: 00:03:47.72

Execution Plan
----------------------------------------------------------
Plan hash value: 1382574215

----------------------------------------------------------------------------
| Id  | Operation         | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |        |   348K|   330M|   323K  (1)| 01:04:46 |
|*  1 |  TABLE ACCESS FULL| WABCDT |   348K|   330M|   323K  (1)| 01:04:46 |
----------------------------------------------------------------------------

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

   1 - filter("A0"."PTC_STR_12TYPEINFOWABCDT" IS NOT NULL AND
              "A0"."PTC_STR_12TYPEINFOWABCDT" LIKE '%中ABCDdddddddd機%')


Statistics
----------------------------------------------------------
         29  recursive calls
          0  db block gets
    1292784  consistent gets
      39729  physical reads
          0  redo size
    3087832  bytes sent via SQL*Net to client
      52158  bytes received via SQL*Net from client
       4696  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
       4694  rows processed
為了降低從磁碟中讀取資料對查詢時間的影響 ,再執行第二次:

SQL> SELECT A0.*
  2   FROM g.wp A0
  3   where A0.ptc_str_12TYPEINFOWABCDT like '%中ABCDdddddddd機%';

4694 rows selected.

Elapsed: 00:00:33.84
Execution Plan
----------------------------------------------------------
Plan hash value: 1382574215

----------------------------------------------------------------------------
| Id  | Operation         | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |        |   348K|   330M|   323K  (1)| 01:04:46 |
|*  1 |  TABLE ACCESS FULL| WABCDT |   348K|   330M|   323K  (1)| 01:04:46 |
----------------------------------------------------------------------------

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

   1 - filter("A0"."PTC_STR_12TYPEINFOWABCDT" IS NOT NULL AND
              "A0"."PTC_STR_12TYPEINFOWABCDT" LIKE '%中ABCDdddddddd機%')


Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
    1292776  consistent gets
          0  physical reads
          0  redo size
    3087832  bytes sent via SQL*Net to client
      52158  bytes received via SQL*Net from client
       4696  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
       4694  rows processed


改寫SQL:

SELECT A0.*
 FROM g.wp A0
 where instr(A0.ptc_str_12TYPEINFOWABCDT,'中ABCDdddddddd機')>0;

SQL> SELECT A0.*
  2   FROM g.wp A0
  3   where instr(A0.ptc_str_12TYPEINFOWABCDT,'中ABCDdddddddd機')>0;

4694 rows selected.

Elapsed: 00:03:36.91

Execution Plan
----------------------------------------------------------
Plan hash value: 1382574215

----------------------------------------------------------------------------
| Id  | Operation         | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |        |   434K|   412M|   323K  (1)| 01:04:46 |
|*  1 |  TABLE ACCESS FULL| WABCDT |   434K|   412M|   323K  (1)| 01:04:46 |
----------------------------------------------------------------------------

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

   1 - filter(INSTR("A0"."PTC_STR_12TYPEINFOWABCDT",'中ABCDdddddddd機')>0)


Statistics
----------------------------------------------------------
         29  recursive calls
          0  db block gets
    1292793  consistent gets
      39727  physical reads
          0  redo size
    3087832  bytes sent via SQL*Net to client
      52158  bytes received via SQL*Net from client
       4696  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
       4694  rows processed

建立函式索引:
create  index g.fx_WABCDT_1 on g.wp(instr(ptc_str_12TYPEINFOWABCDT,'中ABCDdddddddd機')) tablespace gx parallel 16;
alter index g.fx_WABCDT_1 noparallel;


SQL> SELECT A0.*
  2   FROM g.wp A0
  3   where instr(A0.ptc_str_12TYPEINFOWABCDT,'中ABCDdddddddd機')>0;

4694 rows selected.

Elapsed: 00:00:02.31

Execution Plan
----------------------------------------------------------
Plan hash value: 3331311615

-------------------------------------------------------------------------------------------
| Id  | Operation                   | Name        | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |             |   434K|   412M| 12577   (1)| 00:02:31 |
|   1 |  TABLE ACCESS BY INDEX ROWID| WABCDT      |   434K|   412M| 12577   (1)| 00:02:31 |
|*  2 |   INDEX RANGE SCAN          | FX_WABCDT_1 | 78135 |       |   145   (1)| 00:00:02 |
-------------------------------------------------------------------------------------------

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

   2 - access(INSTR("PTC_STR_12TYPEINFOWABCDT",'中ABCDdddddddd機')>0)


Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
       9603  consistent gets
          0  physical reads
          0  redo size
    3085926  bytes sent via SQL*Net to client
      52158  bytes received via SQL*Net from client
       4696  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
       4694  rows processed


邏輯讀從 1292776減少到9603,執行時間由33.84s降低到02.31s。但若用繫結變數的情況,不適合這種方法。

若用繫結變數的情況:
指定hint:
SELECT /*+index(A0 CLS_INDEX) */ A0.*
 FROM WABCDT A0
 where A0.ptc_str_12TYPEINFOWTPART like '中ABCDdddddddd機';
Elapsed: 00:00:05.00

Execution Plan
----------------------------------------------------------
Plan hash value: 4025305430

-----------------------------------------------------------------------------------------
| Id  | Operation                   | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |           |   348K|   330M|   141K  (1)| 00:28:20 |
|   1 |  TABLE ACCESS BY INDEX ROWID| WABCDT    |   348K|   330M|   141K  (1)| 00:28:20 |
|*  2 |   INDEX FULL SCAN           | CLS_INDEX |   356K|       | 44775   (1)| 00:08:58 |
-----------------------------------------------------------------------------------------

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

   2 - filter("A0"."PTC_STR_12TYPEINFOWTPART" IS NOT NULL AND
              "A0"."PTC_STR_12TYPEINFOWTPART" LIKE '中ABCDdddddddd機')


Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
      55985  consistent gets
          0  physical reads
          0  redo size
    3085926  bytes sent via SQL*Net to client
      52158  bytes received via SQL*Net from client
       4696  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
       4694  rows processed

上面有用到index full scan,邏輯讀減少很多,由1292784減少到55985,若所有需要訪問的資料都在記憶體中,那麼執行比較快,上面執行時間為5秒,反之,若需要的資料從磁碟中讀取,是比較慢, 所以採用將索引和表的數全部keep到cache中。

先檢視db_keep_cache_size大小和索引及表的大小,若keep cache不足以存放表和索引,則需要調大引數。
SQL> show parameter keep

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
buffer_pool_keep                     string
control_file_record_keep_time        integer     7
db_keep_cache_size                   big integer 15G

SQL> col segment_name for a20;
SQL> select segment_name,segment_type,bytes/1024/1024 "size(MB)" from dba_segments where owner='G' and segment_name in ('WABCDT','CLS_INDEX');

SEGMENT_NAME         SEGMENT_TYPE         size(MB)
-------------------- ------------------ ----------
WABCDT               TABLE                   10075
CLS_INDEX            INDEX                     367

將索引和表keep到記憶體中:
alter index g.CLS_INDEX storage(buffer_pool keep);
alter table g.wtpart storage(buffer_pool keep);
alter table g.wtpart cache;


SQL> select index_name,buffer_pool from dba_indexes where index_name='CLS_INDEX';

INDEX_NAME                     BUFFER_
------------------------------ -------
CLS_INDEX                      KEEP

SQL> select owner,table_name,CACHE,BUFFER_POOL from dba_tables where table_name='WABCDT' and owner='G';

OWNER                          TABLE_NAME                     CACHE                BUFFER_
------------------------------ ------------------------------ -------------------- -------
G                           WABCDT                           Y                KEEP

上面顯示已有正確keep表和索引到cache中。這樣就可確保除第一次外,其它每次訪問的資料都能從記憶體中獲取。

看下count(*)的情況:

SQL> SELECT count(*)
  2   FROM WABCDT  A0
  3   where A0.ptc_str_12TYPEINFOWABCDT like '%中ABCDdddddddd機%';

Elapsed: 00:00:02.04

Execution Plan
----------------------------------------------------------
Plan hash value: 3203503055

-----------------------------------------------------------------------------------
| Id  | Operation             | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |           |     1 |    11 | 12209   (2)| 00:02:27 |
|   1 |  SORT AGGREGATE       |           |     1 |    11 |            |          |
|*  2 |   INDEX FAST FULL SCAN| CLS_INDEX |   348K|  3742K| 12209   (2)| 00:02:27 |
-----------------------------------------------------------------------------------

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

   2 - filter("A0"."PTC_STR_12TYPEINFOWABCDT" IS NOT NULL AND
              "A0"."PTC_STR_12TYPEINFOWABCDT" LIKE '%中ABCDdddddddd機%')


Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
      46773  consistent gets
          0  physical reads
          0  redo size
        527  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

上面用了INDEX FAST FULL SCAN,走索引的地方是conut(*),並不是where條件。