Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Änderungen des Oracle SQL-Ausführungsplans aufgrund der internen Konvertierung von SYS_OP_C2C

SYS_OP_C2C ist eine internal function was eine implicit conversion durchführt von varchar2 zum national character set mit TO_NCHAR Funktion. Somit ändert sich der Filter im Vergleich zum Filter mit normalem Vergleich vollständig.

Ich bin mir nicht sicher, warum die Anzahl der Zeilen weniger ist , aber ich kann garantieren, dass es mehr sein könnte zu. Die Kostenschätzung ist davon nicht betroffen.

Lassen Sie uns versuchen, Schritt für Schritt in einem Testfall zu sehen.

SQL> CREATE TABLE t AS SELECT 'a'||LEVEL col FROM dual CONNECT BY LEVEL < 1000;

Table created.

SQL>
SQL> EXPLAIN PLAN FOR SELECT * FROM t WHERE col = 'a10';

Explained.

SQL> SELECT * FROM TABLE(dbms_xplan.display);

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
Plan hash value: 1601196873

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

Predicate Information (identified by operation id):
---------------------------------------------------

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------

   1 - filter("COL"='a10')

13 rows selected.

SQL>

So weit, ist es gut. Da es nur eine Zeile mit dem Wert „a10“ gibt, hat der Optimierer eine Zeile geschätzt.

Sehen wir uns die nationale Zeichensatzkonvertierung an.

SQL> EXPLAIN PLAN FOR SELECT * FROM t WHERE col = N'a10';

Explained.

SQL> SELECT * FROM TABLE(dbms_xplan.display);

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
Plan hash value: 1601196873

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |    10 |    50 |     3   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| T    |    10 |    50 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------

   1 - filter(SYS_OP_C2C("COL")=U'a10')

13 rows selected.

SQL>

Was ist hier passiert? Wir können filter(SYS_OP_C2C("COL")=U'a10') sehen , was bedeutet, dass eine interne Funktion angewendet wird und den varchar2 konvertiert Wert zu nvarchar2 . Der Filter hat jetzt 10 Zeilen gefunden.

Dadurch wird auch jede Indexverwendung unterdrückt, da jetzt eine Funktion auf die Spalte angewendet wird. Wir können es optimieren, indem wir einen function-based index erstellen um einen full table scan zu vermeiden .

SQL> create index nchar_indx on t(to_nchar(col));

Index created.

SQL>
SQL> EXPLAIN PLAN FOR SELECT * FROM t WHERE to_nchar(col) = N'a10';

Explained.

SQL> SELECT * FROM TABLE(dbms_xplan.display);

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
Plan hash value: 1400144832

--------------------------------------------------------------------------------------------------
| Id  | Operation                           | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                    |            |    10 |    50 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID BATCHED| T          |    10 |    50 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN                  | NCHAR_INDX |     4 |       |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
---------------------------------------------------

   2 - access(SYS_OP_C2C("COL")=U'a10')

14 rows selected.

SQL>

Wird dies die Ausführungspläne jedoch ähnlich machen? Nein, ich denke mit zwei verschiedenen Zeichensätzen , wird der Filter nicht gleichermaßen angewendet. Der Unterschied liegt also darin.

Meine Forschung sagt,