First_rows optimization Pattern Language sort fuzzy matching problem

Source: Internet
Author: User
Tags create index

The title is longer, but only in this way can the problem be described clearly.

The problem is described in detail as, in First_rows optimization mode, the session sort and comparison method is set to semantic mode, that is, ignoring the case mode, and making a like fuzzy query on the field, which may result in incorrect results.

For a detailed description of the case-insensitive query, refer to: http://yangtingkun.itpub.net/post/468/460324


The following directly look at the phenomenon of the problem:

Sql> CREATE TABLE T1 (ID number PRIMARY KEY, NAME VARCHAR2 (30));

Table has been created.

Sql> CREATE INDEX ind_t1_name on T1 (NAME);

The index has been created.

Sql> INSERT into T1 SELECT rownum, CHR (+ + rownum)
2 from All_objects WHERE rownum <= 26;

26 lines have been created.

Sql> COMMIT;

Submit completed.

Sql> ALTER session SET Nls_comp = linguistic;

The session has changed.

Sql> ALTER session SET nls_sort = Binary_ci;

The session has changed.

Sql> SELECT * from T1 WHERE NAME like ' a% ';

ID NAME
---------- ------------------------------
1 A

sql> SELECT/*+ first_rows * * from T1 WHERE NAME like ' a% ';

No rows selected

As long as you modify any of the key points mentioned above, this error does not occur:

sql> SELECT/*+ all_rows * * from T1 WHERE NAME like ' a% ';

ID NAME
---------- ------------------------------
1 A

sql> SELECT/*+ first_rows * * from T1 WHERE NAME = ' a ';

ID NAME
---------- ------------------------------
1 A

Sql> ALTER session SET nls_sort = BINARY;

The session has changed.

Sql> ALTER session SET Nls_comp = BINARY;

The session has changed.

sql> SELECT/*+ first_rows * * from T1 WHERE NAME like ' a% ';

ID NAME
---------- ------------------------------
1 A

Sql> ALTER session SET Nls_comp = linguistic;

The session has changed.

Sql> ALTER session SET nls_sort = Binary_ci;

The session has changed.

sql> SELECT/*+ first_rows * * from T1 WHERE NAME like ' a% ';

ID NAME
---------- ------------------------------
1 A

sql> SELECT/*+ first_rows * * from T1 WHERE NAME like ' a ';

No rows selected

As you can see from several of the above queries, problems and first_rows,like operations and semantically based ordering are directly related, and here's a look at Oracle's implementation plan in exceptional circumstances:

Sql> SET Autot on EXP
sql> SELECT/*+ first_rows * * from T1 WHERE NAME like ' a ';

No rows selected

Execution plan
----------------------------------------------------------
Plan Hash value:3350237141

-------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU) | Time |
-------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 30 | 35 (0) | 00:00:01 |
|* 1 | VIEW | index$_join$_001 | 1 | 30 | 35 (0) | 00:00:01 |
|* 2 | HASH JOIN | | |
|* 3 | INDEX RANGE SCAN | Ind_t1_name | 1 | 30 | 3 (34) | 00:00:01 |
| 4 | INDEX FAST Full scan| sys_c006622 | 1 | 30 | 33 (0) | 00:00:01 |
-------------------------------------------------------------------------------------------

predicate information (identified by Operation ID):
---------------------------------------------------

1-filter ("NAME" like ' a ')
2-access (Rowid=rowid)
3-access ("NAME" like ' a ')

Note
-----
-Dynamic sampling used for this statement

Since the index does not contain the result of a semantic query, Oracle must access the table to get the final result, so this execution plan is wrong:

Sql> SELECT * from T1 WHERE NAME = ' a ';

ID NAME
---------- ------------------------------
1 A

Execution plan
----------------------------------------------------------
Plan Hash value:3617692013

--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU) | Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 30 | 3 (0) | 00:00:01 |
|* 1 | TABLE ACCESS full| T1 | 1 | 30 | 3 (0) | 00:00:01 |
--------------------------------------------------------------------------

predicate information (identified by Operation ID):
---------------------------------------------------

1-filter (Nlssort ("NAME", ' nls_sort= ' binary_ci ') =hextoraw (' 6100 ')
)

Note
-----
-Dynamic sampling used for this statement

Sql> SELECT/*+ INDEX (T1) * * from T1 WHERE NAME = ' a ';

ID NAME
---------- ------------------------------
1 A

Execution plan
----------------------------------------------------------
Plan Hash value:159298173

-------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU) | Time |
-------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 30 | 827 (1) | 00:00:10 |
|* 1 | TABLE ACCESS by INDEX rowid| T1 | 1 | 30 | 827 (1) | 00:00:10 |
| 2 | INDEX Full SCAN | sys_c006622 | 26 | | 26 (0) | 00:00:01 |
-------------------------------------------------------------------------------------------

predicate information (identified by Operation ID):
---------------------------------------------------

1-filter (Nlssort ("NAME", ' nls_sort= ' binary_ci ') =hextoraw (' 6100 '))

Note
-----
-Dynamic sampling used for this statement

The above two execution plans have explained the crux of the problem, Oracle's ordering of semantics is not indexed, you must access the table or the corresponding function index, and you can refer to the links given at the beginning of the article.

With the First_rows optimization mode, when the operation is like, the Oracle optimizer chooses the wrong execution plan for optimization, and uses an indexed range scan instead of a table, which causes an error:

Sql> SELECT/*+ index_join (T1 ind_t1_name sys_c006622) *
2 from T1
3 WHERE NAME like ' a ';

No rows selected

Execution plan
----------------------------------------------------------
Plan Hash value:3350237141

-------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU) | Time |
-------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 30 | 35 (0) | 00:00:01 |
|* 1 | VIEW | index$_join$_001 | 1 | 30 | 35 (0) | 00:00:01 |
|* 2 | HASH JOIN | | |
|* 3 | INDEX RANGE SCAN | Ind_t1_name | 1 | 30 | 3 (34) | 00:00:01 |
| 4 | INDEX FAST Full scan| sys_c006622 | 1 | 30 | 33 (0) | 00:00:01 |
-------------------------------------------------------------------------------------------

predicate information (identified by Operation ID):
---------------------------------------------------

1-filter ("NAME" like ' a ')
2-access (Rowid=rowid)
3-access ("NAME" like ' a ')

Note
-----
-Dynamic sampling used for this statement

There is no use of first_rows now, and the use of hint has achieved the same effect. The solution to this problem is through hint to avoid the occurrence of index range scans.

Sql> ALTER session SET Optimizer_mode = first_rows;

The session has changed.

Sql> SELECT * from T1 WHERE NAME like ' a ';

No rows selected

Execution plan
----------------------------------------------------------
Plan Hash value:3350237141

-------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU) | Time |
-------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 30 | 35 (0) | 00:00:01 |
|* 1 | VIEW | index$_join$_001 | 1 | 30 | 35 (0) | 00:00:01 |
|* 2 | HASH JOIN | | |
|* 3 | INDEX RANGE SCAN | Ind_t1_name | 1 | 30 | 3 (34) | 00:00:01 |
| 4 | INDEX FAST Full scan| sys_c006622 | 1 | 30 | 33 (0) | 00:00:01 |
-------------------------------------------------------------------------------------------

predicate information (identified by Operation ID):
---------------------------------------------------

1-filter ("NAME" like ' a ')
2-access (Rowid=rowid)
3-access ("NAME" like ' a ')

Note
-----
-Dynamic sampling used for this statement

Sql> SELECT/*+ Full (T1)/* from T1 WHERE NAME like ' a ';

ID NAME
---------- ------------------------------
1 A

Execution plan
----------------------------------------------------------
Plan Hash value:3617692013

--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU) | Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 30 | 3 (0) | 00:00:01 |
|* 1 | TABLE ACCESS full| T1 | 1 | 30 | 3 (0) | 00:00:01 |
--------------------------------------------------------------------------

predicate information (identified by Operation ID):
---------------------------------------------------

1-filter ("NAME" like ' a ')

Note
-----
-Dynamic sampling used for this statement

Sql> SELECT/*+ no_index (T1) * * from T1 WHERE NAME like ' a ';

ID NAME
---------- ------------------------------
1 A

Execution plan
----------------------------------------------------------
Plan Hash value:3617692013

--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU) | Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 30 | 3 (0) | 00:00:01 |
|* 1 | TABLE ACCESS full| T1 | 1 | 30 | 3 (0) | 00:00:01 |
--------------------------------------------------------------------------

predicate information (identified by Operation ID):
---------------------------------------------------

1-filter ("NAME" like ' a ')

Note
-----
-Dynamic sampling used for this statement

The query metalink,oracle the bug explicitly in Doc id:note:5252496.8, which is fixed in Oracle10.2.0.4 and 11.1.0.6.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.