zoukankan      html  css  js  c++  java
  • like查询如何有索引效果

    like查询如何有索引效果

            在oracle里的一个超级大的表中,我们的where条件的列有建索引的话,会走索引唯一扫描INDEX UNIQUE SCAN。如select * from table where code = 'Cod25',而如下这些语句哪些会走索引呢?

    Sql代码  收藏代码
    1. select * from table where code like 'Code2%'  
    2. select * from table where code like '%ode2%'  
    3. select * from table where code like '%ode2'  

    经验证:
            select * from table where code like 'Cod2%'会走索引,且走的是INDEX RANGE SCAN,而这样写like '%xxx'或'%xxx%'不会走索引,感觉就像组合索引一样,直接用索引第一个字段会走索引,而用索引第二个字段则不会走索引。

            当然,如果select * from table where code like 'Cod%' 查询的结果就是所有记录,走索引和full table scaN的结果是一样的,所以也将是全表扫描。可以换成select * from table where code like 'Code2%'或者 select count(*) from table where code like 'Cod%'试试,应该不会是全表扫描。

     

    二.优化like查询

    1.经上面测试,like查询结果如下:
            a.like %keyword    索引失效,使用全表扫描。但可以通过
    翻转函数+like前模糊查询+建立翻转函数索引=走翻转函数索引,不走全表扫描。如where reverse(code) like reverse('%Code2')
            b.like keyword%    索引有效。  
            c.like %keyword%   索引失效,也无法使用反向索引。
    2.优化like查询:
            a.使用其它函数来进行模糊查询,如果出现的位置大于0,表示包含该字符串,查询效率比like要高。

            1)在oracle中,可以用instr,这样查询效果很好,速度很快。

    Sql代码  收藏代码
    1. select count(*) from table t where instr(t.code,'Cod2%') > 0  
            2)在mysql中,可以用locate和position函数,如table.field like '%AAA%'可以改为locate('AAA', table.field) > 0或POSITION('AAA' IN table.field)>0。

            LOCATE(substr,str)、POSITION(substr IN str):返回子串 substr 在字符串 str 中第一次出现的位置。如果子串 substr 在 str 中不存在,返回值为 0。

            3)在sql server中,可以给字段建立全文索引,用contains来检索数据,CONTAINS用法,可以参考:http://bijian1013.iteye.com/blog/2232872

            b.查询%xx的记录  

    Sql代码  收藏代码
    1. select count(c.c_ply_no) as COUNT  
    2.   from Policy_Data_All c, Item_Data_All i  
    3.  where c.c_ply_no = i.c_ply_no  
    4.    and i.C_LCN_NO like ’%245′  
            在执行的时候,执行计划显示,消耗值,io值,cpu值均非常大,原因是like后面前模糊查询导致索引失效,进行全表扫描。
            解决方法:这种只有前模糊的sql可以改造如下写法
    Sql代码  收藏代码
    1. select count(c.c_ply_no) as COUNT  
    2.   from Policy_Data_All c, Item_Data_All i  
    3.  where c.c_ply_no = i.c_ply_no  
    4.    and reverse(i.C_LCN_NO) like reverse('%245')  
            使用翻转函数+like前模糊查询+建立翻转函数索引=走翻转函数索引,不走全扫描。有效降低消耗值,io值,cpu值这三个指标,尤其是io值的降低。

            建函数索引:create index p_idx on table(instr(code,'Code2'));需进一步说明的是,这样的话,只有where instr(code,'Code2')才会走INDEX RANGE SCAN,其它如where instr(code, 'Code3')会走INDEX FAST FULL SCAN甚至TABLE ACCESS FULL。

            另外,select * from table where upper(code) = 'abcD',会走TABLE ACCESS FULL。如果建函数索引create index idx_upper on table(upper(code));之后,将会是INDEX RANGE SCAN,如下所示:

     

    PS:一般索引和函数索引的区别

    1.一般的索引:

    Sql代码  收藏代码
    1. create index P_IDX ON TABLE1(COLUMN1);  

            当执行SELECT * FROM TABLE1 WHERE COLUMN1 = XXX 时会用到索引。

    2.函数索引:

    Sql代码  收藏代码
    1. CREATE INDEX P_IDX ON TABLE1(SUBSTR(COLUMN1,0,5));  

            当执行SELECT * FROM TABLE1 WHERE SUBSTR(COLUMN1,0,5) = XXX 时会用到索引。但执行SELECT * FROM TABLE1 WHERE COLUMN1 = XXX时是不会用到索引的。一般情况下是最好不用建函数索引。



    转自:https://blog.csdn.net/wangjunjun2008/article/details/52131668


    以通配符(%)开始的like字符串,走索引



    了解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');

    问题解决。


  • 相关阅读:
    What's different between Ctrl+Z and Ctrl+C in Unix command line?
    bitbucket使用,经验总结
    SpringMVC 强大的注解方式,走一个流程,看看,这些注解用过么
    java异常处理,需要考虑的流程
    两个日期之间相差的天数
    vue 路由面试题
    promise
    es6面试题
    谈谈你是如何理解 JS 异步编程的,EventLoop、消息队列都是做什么的,什么是宏任务,什么是微任务?
    使用高阶函数实现Array对象的方法
  • 原文地址:https://www.cnblogs.com/thewindkee/p/12873180.html
Copyright © 2011-2022 走看看