Talk About Network

Google


Register and Login
Nick
Password
Register create new account Sign up is FREE and you can post replies, new topics, bookmark posts and more!
Recover lost password


Data Bases > Oracle Server > Re: Differences...
Latest [ Topics | Posts ] Archive Post A New Topic Post a Reply
<< Topic < Post Post 4 of 6 Topic 16522 of 17269
Post > Topic >>

Re: Differences in Range Scan Performance between Binary and NLS

by joel garry <joel-garry@[EMAIL PROTECTED] > May 7, 2008 at 11:29 AM

On May 6, 2:36=C2=A0pm, Pat <pat.ca...@[EMAIL PROTECTED]
> wrote:
> On May 6, 2:26 pm, joel garry <joel-ga...@[EMAIL PROTECTED]
> wrote:
>
>
>
>
>
> > On May 6, 1:16 pm, Pat <pat.ca...@[EMAIL PROTECTED]
> wrote:
>
> > > I have a table set with about 340k rows in it. User's execute
queries
> > > against this table for arbitrary search strings which are resolved
> > > against the name table in the column. The table contains mixed case,
> > > but the users expect to match their search regardless of case. So,
for=

> > > example, both of these should match a search term of "badg":
>
> > > ARabidBadger
> > > somebadglowercase
>
> > > A typical search, for all those entries whose name contains "badg"
> > > would look like this:
>
> > > SELECT "sys_id" FROM (SELECT /*+ FIRST_ROWS(250) */ a.*, ROWNUM rnum
> > > FROM (SELECT cmdb_ci0."sys_id" FROM cmdb_ci cmdb_ci0 =C2=A0WHERE
> > > lower(cmdb_ci0."name") LIKE '%badge%' ORDER BY
lower(cmdb_ci0."name"))=

> > > a where ROWNUM <=3D 250) WHERE rnum > 0
>
> > > To make this query efficient, I added a covering index
>
> > > create index cmdb_ci_lower_name_sys_id on cmdb_ci (lower("name"),
> > > "sys_id");
>
> > > And our query plan looks like this and completes in about 120 ms.
This=

> > > was worst case since only 1 row was returned. Short search strings
> > > like "b" will hit their stop key quickly and exit after finding 250
> > > matches without having to exhaust the index.
>
> > > Still, worst case, this query does a full index scan in about 120ms;
>
> > > SQL> SELECT "sys_id" FROM (SELECT /*+ FIRST_ROWS(250) */ a.*, ROWNUM
> > > rnum FROM (SELECT cmdb_ci0."sys_id" FROM cmdb_ci cmdb_ci0
=C2=A0WHERE
> > > lower(cmdb_ci0."name") LIKE '%badge%' ORDER BY
lower(cmdb_ci0."name"))=

> > > a where ROWNUM <=3D 250) WHERE rnum > 0;
>
> > > Elapsed: 00:00:00.12
>
> > > Execution Plan
> > > ----------------------------------------------------------
> > > Plan hash value: 424525705
>
> > >
----------------------------------------------------------------------=
-----=C2=AD=C2=AD---------------------
> > > | Id =C2=A0| Operation =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0| Name
=C2=A0=
 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0|
Rows=
 =C2=A0| Bytes | Cost (%CPU)|
> > > Time =C2=A0 =C2=A0 |
> > >
----------------------------------------------------------------------=
-----=C2=AD=C2=AD---------------------
> > > | =C2=A0 0 | SELECT STATEMENT =C2=A0 | =C2=A0 =C2=A0 =C2=A0 =C2=A0
=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 | =C2=A0 250 |
1=
1750 | =C2=A0 =C2=A046 =C2=A0 (0)|
> > > 00:00:01 |
> > > |* =C2=A01 | =C2=A0VIEW =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0
=C2=
=A0| =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0
=
=C2=A0 =C2=A0 =C2=A0 | =C2=A0 250 | 11750 | =C2=A0 =C2=A046 =C2=A0 (0)|
00:0=
0:01 |
> > > |* =C2=A02 | =C2=A0 COUNT STOPKEY =C2=A0 =C2=A0| =C2=A0 =C2=A0
=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 |
=C2=
=A0 =C2=A0 =C2=A0 | =C2=A0 =C2=A0 =C2=A0 | =C2=A0 =C2=A0 =C2=A0 =C2=A0
=C2=
=A0 =C2=A0| =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0|
> > > | =C2=A0 3 | =C2=A0 =C2=A0VIEW =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0
=C2=
=A0| =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0
=
=C2=A0 =C2=A0 =C2=A0 | =C2=A0 251 | =C2=A08534 | =C2=A0 =C2=A046 =C2=A0
(0)|=
 00:00:01
> > > |
> > > |* =C2=A04 | =C2=A0 =C2=A0 INDEX FULL SCAN|
CMDB_CI_LOWER_NAME_SYS_ID =
| 16997 |
> > > 813K| =C2=A0 =C2=A046 =C2=A0 =C2=A0 =C2=A0(0)| 00:00:01 |
> > >
----------------------------------------------------------------------=
-----=C2=AD=C2=AD---------------------
>
> > > Predicate Information (identified by operation id):
> > > ---------------------------------------------------
>
> > > =C2=A0 =C2=A01 - filter("RNUM">0)
> > > =C2=A0 =C2=A02 - filter(ROWNUM<=3D250)
> > > =C2=A0 =C2=A04 - filter(LOWER("name") LIKE '%badge%')
>
> > > Statistics
> > > ----------------------------------------------------------
> > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 141 =C2=A0recursive calls
> > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0 =C2=A0db block gets
> > > =C2=A0 =C2=A0 =C2=A0 =C2=A02964 =C2=A0consistent gets
> > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0 =C2=A0physical reads
> > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0 =C2=A0redo size
> > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 439 =C2=A0bytes sent via SQL*Net to
client=

> > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 400 =C2=A0bytes received via SQL*Net
from =
client
> > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 2 =C2=A0SQL*Net roundtrips
to/from =
client
> > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0 =C2=A0sorts (memory)
> > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0 =C2=A0sorts (disk)
> > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 1 =C2=A0rows processed
>
> > > Recently though, we started storing NLS characters in this column
> > > (european customers), so we'll have values like:
>
> > > badger
> > > b=C3=A4dger <-- note the accented a
>
> > > The users want both of the above to collate next to each other.
>
> > > So we, not unnaturally, put the database in linguisitc mode:
>
> > > alter session set nls_sort=3Dgerman;
> > > alter session set nls_comp=3Dlinguistic;
>
> > > Then we issue the same query. The query plan here involves a sort,
but=

> > > the query returns a grand total of 1 record, so the sort isn't
> > > material to the response time.
>
> > ...
>
> > > 1) Am I doing something wrong here? Why does putting the system into
> > > NLS_SORT and NLS_COMP make this big a difference on performance?
> > > 2) Is there an index I should add here that would allow some form of
> > > efficient querying across this set? I know I'm going to have to do a
> > > full scan here (contains queries being what they are), but why is my
> > > full scan 10X slower in linguistic mode?
> > > 3) Is there some other recommended approach to getting linguistic
> > > collation working efficiently? Shadow columns aren't really
practical
> > > here (and even then I'm not sure what I'd put in the shadow unless I
> > > wrote my own german to english unaccenter).
>
> > > Any help would be much appreciated.
>
> > See metalink Note:30779.1
>
> > "Setting NLS_SORT to anything other than BINARY causes a sort to use a
> > full table scan, regardless of the path chosen by the optimizer.
> > BINARY is the exception because indexes are built according to a
> > binary order of keys. Thus the optimizer can use an index to satisfy
> > the ORDER BY clause when NLS_SORT is set to BINARY. If NLS_SORT is set
> > to any linguistic sort, the optimizer must include a full table scan
> > and a full sort in the execution plan. =C2=A0"
>
> > Things may be different in different versions, I wouldn't know.
>
> > jg
> > --
> > @[EMAIL PROTECTED]
 is
bogus.http://forums.oracle.com/forums/thread.jspa?messageID=
=3D2507441=EE=85=90?
>
> Even though my query plan says INDEX FAST FULL SCAN he's actually
> doing TABLE ACCESS FULL?

I dunno, I think tracing would be called for to see for sure.  The
idea of lying optimizer plans that are obtained for things actually
running is a bit of a thought-provoker for me.

> SQL> select "name" from cmdb_ci where "sys_id" like '%abc%' order by
> "name";
>
> 1530 rows selected.
>
> Elapsed: 00:00:00.20
>
> Execution Plan
> ----------------------------------------------------------
> Plan hash value: 502630801
>
>
--------------------------------------------------------------------------=
-=C2=AD-----------
> | Id =C2=A0| Operation =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0| Name =C2=A0
=C2=
=A0| Rows =C2=A0| Bytes |TempSpc| Cost (%CPU)|
> Time =C2=A0 =C2=A0 |
>
--------------------------------------------------------------------------=
-=C2=AD-----------
> | =C2=A0 0 | SELECT STATEMENT =C2=A0 | =C2=A0 =C2=A0 =C2=A0 =C2=A0 |
16997=
 | =C2=A0 813K| =C2=A0 =C2=A0 =C2=A0 | =C2=A03190 =C2=A0 (3)|
> 00:00:39 |
> | =C2=A0 1 | =C2=A0SORT ORDER BY =C2=A0 =C2=A0 | =C2=A0 =C2=A0 =C2=A0
=C2=
=A0 | 16997 | =C2=A0 813K| =C2=A02008K| =C2=A03190 =C2=A0 (3)|
> 00:00:39 |
> |* =C2=A02 | =C2=A0 TABLE ACCESS FULL| CMDB_CI | 16997 | =C2=A0 813K|
=C2=
=A0 =C2=A0 =C2=A0 | =C2=A02979
> (3)| 00:00:36 |
>
--------------------------------------------------------------------------=
-=C2=AD-----------
>
> Predicate Information (identified by operation id):
> ---------------------------------------------------
>
> =C2=A0 =C2=A02 - filter("sys_id" LIKE '%abc%')
>
> Statistics
> ----------------------------------------------------------
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 148 =C2=A0recursive calls
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0 =C2=A0db block gets
> =C2=A0 =C2=A0 =C2=A0 13165 =C2=A0consistent gets
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0 =C2=A0physical reads
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0 =C2=A0redo size
> =C2=A0 =C2=A0 =C2=A0 40810 =C2=A0bytes sent via SQL*Net to client
> =C2=A0 =C2=A0 =C2=A0 =C2=A01511 =C2=A0bytes received via SQL*Net from
clie=
nt
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 103 =C2=A0SQL*Net roundtrips to/from client
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 1 =C2=A0sorts (memory)
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0 =C2=A0sorts (disk)
> =C2=A0 =C2=A0 =C2=A0 =C2=A01530 =C2=A0rows processed
>
> So in this case, a TABLE ACCESS FULL, followed by a sort in binary
> mode is 5x faster than an index full scan in linguistic mode?
>
> If the only problem was that linguistic forced him to table scan, I'd
> expect him to return data in 200ms or so (the time a table scan takes)
> as opposed to 1.3 seconds, neh?-

Well, maybe something else is going on, like applying some semantics
to every row...  been too long since I worked with this stuff to do
anything but guess.

jg
--
@[EMAIL PROTECTED]
 is bogus.
Now not only do you drop your keys or phone in the toilet, it
automatically flushes if you stand up to get them.
 




 6 Posts in Topic:
Differences in Range Scan Performance between Binary and NLS Ind
Pat <pat.casey@[EMAIL   2008-05-06 13:16:56 
Re: Differences in Range Scan Performance between Binary and NLS
joel garry <joel-garry  2008-05-06 14:26:43 
Re: Differences in Range Scan Performance between Binary and NLS
Pat <pat.casey@[EMAIL   2008-05-06 14:36:47 
Re: Differences in Range Scan Performance between Binary and NLS
joel garry <joel-garry  2008-05-07 11:29:51 
Re: Differences in Range Scan Performance between Binary and NLS
Pat <pat.casey@[EMAIL   2008-05-07 12:29:06 
Re: Differences in Range Scan Performance between Binary and NLS
"Jonathan Lewis"  2008-05-10 10:49:52 

Post A Reply:
  Go here to Signup

AddThis Feed Button


About - Advertising - Contact - Frequently Asked Questions - Privacy Policy - Terms of Use - Signup

Contact
tan12V112 Sat Oct 11 22:21:37 CDT 2008.