zoukankan      html  css  js  c++  java
  • 以通配符(%)开始的like字符串,走索引

    在对oracle的SQL优化过程中经常会遇到【like'%abc'】破坏索引的问题,但是如果真有此类需求,该如何在不破坏索引的基础上进行查询呢。

    [sql] view plain copy
    sys@mescp> select reverse('123') from dual;  
      
    REVERSE('123')  
    --------------------------------  
    321  
    1 row selected.  
      
    sys@mescp> create table test_like as select object_id,object_name from dba_objects;  
      
    Table created.  
      
    sys@mescp> create index test_like__name on test_like(object_name);  
      
    Index created.  
      
    sys@mescp> create index test_like__name_reverse on test_like(reverse(object_name));  
      
    Index created.  
      
    sys@mescp> analyze table test_like compute statistics for table for all indexes;  
      
    Table analyzed.  
      
    sys@mescp> set autotrace trace exp  
      
    -- '常量开头的like , 会利用index ,没问题…… '  
      
    sys@mescp> select * from test_like where object_name like AS%';  
      
    Execution Plan  
      
    ----------------------------------------------------------  
    0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=655 Bytes=15720)  
    1 0 TABLE ACCESS (BY INDEX ROWID) OF 'TEST_LIKE' (Cost=2 Card=655Bytes=15720)  
    2 1 INDEX (RANGE SCAN) OF 'TEST_LIKE__NAME' (NON-UNIQUE) (Cost=2 Card=118)  
    --'开头和结尾都是 % ,对不起,很难优化'  
    sys@mescp> select * from test_like where object_name like '%%';  
      
    Execution Plan  
      
    ----------------------------------------------------------  
    0 SELECT STATEMENT Optimizer=CHOOSE (Cost=6 Card=655 Bytes=15720)  
    1 0 TABLE ACCESS (FULL) OF 'TEST_LIKE' (Cost=6 Card=655 ytes=15720)  
      
    -- '以常量结束,直接写的时候是不能应用index的'  
    sys@mescp> select * from test_like where object_name like '%S';  
    Execution Plan  
    ----------------------------------------------------------  
    0 SELECT STATEMENT Optimizer=CHOOSE (Cost=6 Card=655 Bytes=15720)  
      
    1 0 TABLE ACCESS (FULL) OF 'TEST_LIKE' (Cost=6 Card=655 Bytes=15720)  
    --'以常量结束的,加个reverse 函数,又可以用上index了'  
      
    sys@mescp> select * from test_like where reverse(object_name)like reverse('%AS');  
    Execution Plan  
      
    ----------------------------------------------------------  
      
    0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=655 Bytes=15720)  
    1 0 TABLE ACCESS (BY INDEX ROWID) OF 'TEST_LIKE' (Cost=2 Card=655 Bytes=15720)  
      
    2 1 INDEX (RANGE SCAN) OF 'TEST_LIKE__NAME_REVERSE' (NON-UNIQUE) (Cost=2 Card=118)  

    了解SQL的同学,都知道,like关键字可以走索引,只要字符串不是以通配符(%)开始。

    如果类似 like "%xxx" 的sql,如何走索引呢?基于REVERSE()函数来创建一个函数索引。

    1、准备数据:

    CREATE TABLE jka AS SELECT ROWNUM id, dbms_random.string('x',10) v FROM dual CONNECT BY LEVEL <= 10000;

    2、创建原始索引:

    CREATE INDEX jka_normal ON jka (v);
    
    BEGIN
      dbms_stats.gather_table_stats
        (USER
        ,'JKA'
        ,estimate_percent=>100
        ,cascade=>TRUE);
    END;

    3、以下SQL基于jka_normal索引走范围扫描:

    SELECT * FROM jka WHERE v LIKE 'ABC%';

    4、但是下面的SQL将走全表扫描(不会使用索引):

    SELECT * FROM jka WHERE v LIKE '%ABC';

    5、现在,创建一个函数索引(不要与反向索引[REVERSE INDEX]混淆):

    CREATE INDEX jka_reverse ON jka(REVERSE(v));
    
    BEGIN
      dbms_stats.gather_table_stats
        (USER
        ,'JKA'
        ,estimate_percent=>100
        ,cascade=>TRUE);
    END;

    6、下面的SQL将基于jka_reverse索引走范围扫描:

    SELECT * FROM jka WHERE REVERSE(v) LIKE REVERSE('%ABC');

    问题解决。

  • 相关阅读:
    对人脑学习的一些领悟
    象形法,快速记忆魔方公式
    公司招聘
    微信游戏《全民炫舞》开发公司h3d2 engine和QQ炫舞2 布料系统技术介绍
    四维几何世界中的盒子
    HI-LO计数法,赌桌,与机会
    离开天朝,跑到新加坡了
    精选19款华丽的HTML5动画和实用案例
    精选29款非常实用的jQuery应用插件
    【特别推荐】8个富有创意的jQuery/CSS3插件
  • 原文地址:https://www.cnblogs.com/a8457013/p/7826097.html
Copyright © 2011-2022 走看看