Oracle FAQ Your Portal to the Oracle Knowledge Grid
HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US
 

Home -> Community -> Usenet -> c.d.o.server -> Re: Oracle 10g2 LIKE operator and case-insensitive issues

Re: Oracle 10g2 LIKE operator and case-insensitive issues

From: Steve Chien <stevechien_at_wisagetech.com>
Date: Fri, 11 May 2007 16:06:28 +0800
Message-ID: <1n8843p0hnt78s1clnictrgiio4ndsit2o@4ax.com>


On 11 May 2007 00:41:48 -0700, Cristian Cudizio <cristian.cudizio_at_yahoo.it> wrote:

>On May 11, 9:23 am, Steve Chien <stevech..._at_wisagetech.com> wrote:
>> On 11 May 2007 00:09:08 -0700, Cristian Cudizio
>>
>>
>>
>> <cristian.cudi..._at_yahoo.it> wrote:
>> >On May 11, 9:06 am, Steve Chien <stevech..._at_wisagetech.com> wrote:
>> >> On 11 May 2007 00:00:03 -0700, Cristian Cudizio
>>
>> >> <cristian.cudi..._at_yahoo.it> wrote:
>> >> >On May 11, 8:50 am, Steve Chien <stevech..._at_wisagetech.com> wrote:
>> >> >> Hi,
>>
>> >> >> We're curerrently facing some performance issues related to the
>> >> >> "LIKE" operator in Oracle 10g2. Here is what we encountered.
>>
>> >> >> We have a Oracle 10g2 database which has the following
>> >> >> characteristics.
>>
>> >> >> NLS_CHARACTERSET => AL32UTF8
>> >> >> NLS_NCHAR_CHARACTERSET => AL16UTF16
>> >> >> NLS_RDBMS_VERSION => 10.2.0.1.0
>>
>> >> >> We created a table like below.
>> >> >> -- creates test table
>> >> >> CREATE TABLE MYTEST
>> >> >> (id NUMBER(10, 0) NOT NULL,
>> >> >> str1 VARCHAR2(128) NOT NULL,
>> >> >> str2 NVARCHAR2(128) NOT NULL);
>>
>> >> >> Then, we populated with some random data.
>> >> >> -- PL/SQL for creating random data
>> >> >> BEGIN
>> >> >> DBMS_RANDOM.SEED('thisisjustatest');
>> >> >> FOR i IN 1 .. 100000 LOOP
>> >> >> INSERT INTO MYTEST VALUES(i, DBMS_RANDOM.STRING('P', 64),
>> >> >> DBMS_RANDOM.STRING('P', 64));
>> >> >> END LOOP;
>> >> >> INSERT INTO MYTEST VALUES(100001, 'steve', 'chien');
>> >> >> INSERT INTO MYTEST VALUES(100002, 'STEVE', 'CHIEN');
>> >> >> END;
>>
>> >> >> Afterwards, we created the indexes.
>> >> >> -- creates indexes
>> >> >> CREATE INDEX AK1_ID_MYTEST ON MYTEST(ID);
>> >> >> CREATE INDEX AK2_STR1_MYTEST ON MYTEST(STR1);
>> >> >> CREATE INDEX AK3_STR2_MYTEST ON MYTEST(STR2);
>>
>> >> >> With the "autotrace" turned on , NLS_COMP set to BINARY, and
>> >> >> NLS_SORT set to BINARY in SQLPlus, we did two experiments.
>>
>> >> >> CASE I.
>> >> >> select * from mytest where str1 = 'steve'
>>
>> >> >> Plan hash value: 587925449
>>
>> >> >> -----------------------------------------------------------------------------------------------
>> >> >> | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
>> >> >> -----------------------------------------------------------------------------------------------
>> >> >> | 0 | SELECT STATEMENT | | 1 | 209 | 5 (0)| 00:00:01 |
>> >> >> | 1 | TABLE ACCESS BY INDEX ROWID| MYTEST | 1 | 209 | 5 (0)| 00:00:01 |
>> >> >> |* 2 | INDEX RANGE SCAN | AK2_STR1_MYTEST | 1 | | 3 (0)| 00:00:01 |
>> >> >> -----------------------------------------------------------------------------------------------
>>
>> >> >> Predicate Information (identified by operation id):
>> >> >> ---------------------------------------------------
>>
>> >> >> 2 - access("STR1"='steve')
>>
>> >> >> CASE II.
>> >> >> select * from mytest where str1 like 'steve%';
>>
>> >> >> Plan hash value: 587925449
>>
>> >> >> -----------------------------------------------------------------------------------------------
>> >> >> | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
>> >> >> -----------------------------------------------------------------------------------------------
>> >> >> | 0 | SELECT STATEMENT | | 1 | 209 | 5 (0)| 00:00:01 |
>> >> >> | 1 | TABLE ACCESS BY INDEX ROWID| MYTEST | 1 | 209 | 5 (0)| 00:00:01 |
>> >> >> |* 2 | INDEX RANGE SCAN | AK2_STR1_MYTEST | 1 | | 3 (0)| 00:00:01 |
>> >> >> -----------------------------------------------------------------------------------------------
>>
>> >> >> Predicate Information (identified by operation id):
>> >> >> ---------------------------------------------------
>>
>> >> >> 2 - access("STR1" LIKE 'steve')
>>
>> >> >> Here is what bothered us more... We actually wanted to do
>> >> >> case-insensitive searches & sorts on columnes str1 & str2. We dropped
>> >> >> the indexes and re-created them as blows.
>>
>> >> >> - drop & re-create indexes
>> >> >> DROP INDEX AK1_ID_MYTEST;
>> >> >> DROP INDEX AK2_STR1_MYTEST;
>> >> >> DROP INDEX AK3_STR2_MYTEST;
>>
>> >> >> - creates indexes
>> >> >> CREATE INDEX AK1_ID_MYTEST ON MYTEST(ID)
>> >> >> CREATE INDEX AK2_STR1_MYTEST ON MYTEST(NLSSORT(STR1,
>> >> >> 'NLS_SORT=GENERIC_M_CI'));
>> >> >> CREATE INDEX AK3_STR2_MYTEST ON MYTEST(NLSSORT(STR2,
>> >> >> 'NLS_SORT=GENERIC_M_CI'));
>>
>> >> >> With "autotrace" turned on, NLS_COMP set to LINGUISTIC, and NLS_SORT
>> >> >> set to GENERIC_M_CI in SQLPlus, we dir the following two test cases.
>>
>> >> >> CASE I.
>> >> >> select * from mytest where str1 = 'steve'
>>
>> >> >> Plan hash value: 3883648009
>>
>> >> >> ------ -
>> >> >> -----------------------------------------
>> >> >> | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
>> >> >> ------ -
>> >> >> -----------------------------------------
>> >> >> | 0 | SELECT STATEMENT | | 851 | 173K| 404 (1)| 00:00:05 |
>> >> >> | 1 | TABLE ACCESS BY INDEX ROWID| MYTEST | 851 | 173K| 404 (1)| 00:00:05 |
>> >> >> |* 2 | INDEX RANGE SCAN | AK2_STR1_MYTEST | 340 | | 3 (0)| 00:00:01 |
>> >> >> ------ -
>> >> >> -----------------------------------------
>>
>> >> >> Predicate Information (identified by operation id):
>> >> >> ---------------------------------------------------
>>
>> >> >> 2 - access(NLSSORT("STR1",'nls_sort=''GENERIC_M_CI''')=HEXTORAW('
>> >> >> 024F025501FE026101FE00000202020202') )
>>
>> >> >> CASE II.
>> >> >> select * from mytest where str1 like 'steve%';
>>
>> >> >> Plan hash value: 1692938441
>>
>> >> >> ------ - -----------------------------------------
>> >> >> | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
>> >> >> ------ - -----------------------------------------
>> >> >> | 0 | SELECT STATEMENT | | 32 | 6688 | 791 (1)| 00:00:10 |
>> >> >> |* 1 | TABLE ACCESS FULL| MYTEST | 32 | 6688 | 791 (1)| 00:00:10 |
>> >> >> ------ - -----------------------------------------
>>
>> >> >> Predicate Information (identified by operation id):
>> >> >> ---------------------------------------------------
>>
>> >> >> 1 - filter("STR1" LIKE 'steve%')
>>
>> >> >> Oracle was using the "TABLE ACCESS FULL" to handle the "LIKE"
>> >> >> operator. It's extremely slow and we wondered why it couldn't use the
>> >> >> "INDEX RANGE SCAN" anymore.
>>
>> >> >> Thanks for any suggestion!
>>
>> >> >> - Steve
>>
>> >> >On asktom.oracle.com you can find useful information about Oracle db
>> >> >case sensitive. However
>> >> >from 10gR2 you can use
>> >> >NLS_COMP = LINGUISTIC
>> >> >NLS_SORT = BINARY_CI
>>
>> >> >it make searches case insensitive
>>
>> >> >Bye
>> >> > Cristian Cudizio
>>
>> >> >http://oracledb.wordpress.com
>> >> >http://cristiancudizio.wordpress.com
>>
>> >> Hi,
>>
>> >> We did try the BINARY_CI too. However, the outstanding question is
>> >> that the Oracle was not using the index with the "LIKE" operator.
>>
>> >> Any suggestion?
>>
>> >> Thanks!
>>
>> >> - Steve
>>
>> >Yes, hear me, use
>> >NLS_COMP = LINGUISTIC
>> >NLS_SORT = BINARY_CI
>>
>> >it works on 10gR2
>>
>> >Bye
>> > Cristian Cudizio
>>
>> >http://oracledb.wordpress.com
>> >http://cristiancudizio.wordpress.com
>>
>> Hi,
>>
>> I dropped the orignal index and did,
>>
>> c
>
>>
>> With "autotrace" turned on, NLS_COMP set to LINGUISTIC, and NLS_SORT
>> set to BINARY_CI in SQLPlus, we ran the following test again.
>>
>> select * from mytest where str1 like 'steve%';
>>
>> We got the following plan,
>>
>> Plan hash value: 1692938441
>>
>> ----------------------------------------------------------------------------
>> | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
>> ----------------------------------------------------------------------------
>> | 0 | SELECT STATEMENT | | 32 | 6688 | 791 (1)| 00:00:10 |
>> |* 1 | TABLE ACCESS FULL| MYTEST | 32 | 6688 | 791 (1)| 00:00:10 |
>> ----------------------------------------------------------------------------
>>
>> Predicate Information (identified by operation id):
>> ---------------------------------------------------
>>
>> 1 - filter("STR1" LIKE 'steve%')
>>
>> Note
>> -----
>> - dynamic sampling used for this statement
>>
>> Still "TABLE ACCESS FULL SCAN"... Did I miss anything?
>>
>> Thanks!
>>
>> - Steve
>
>Yes,
>create index normally,
>create index ak2_str1_mytest on mytest(str1)) ;
>
>Bye
>Cristian Cudizio
>
>http://oracledb.wordpress.com
>http://cristiancudizio.wordpress.com

Hi,

  We dropped the index and recreated as below.

create index ak2_str1_mytest on mytest(str1) COMPUTE STATISTICS;

  With "autotrace" turned on, NLS_COMP set to LINGUISTIC, and NLS_SORT set to BINARY_CI, we still got the following plan.

select * from mytest where str1 like 'steve%';

Plan hash value: 1692938441



| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
|   0 | SELECT STATEMENT  |        |     2 |   418 |   791   (1)| 00:00:10 |
|*  1 |  TABLE ACCESS FULL| MYTEST |     2 |   418 |   791   (1)| 00:00:10 |
----------------------------------------------------------------------------

Predicate Information (identified by operation id):


   1 - filter("STR1" LIKE 'steve%')

Note


  Still "TABLE ACCESS FULL SCAN"? Any thought?

Received on Fri May 11 2007 - 03:06:28 CDT

Original text of this message

HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US