Oracle
 sql >> Base de données >  >> RDS >> Oracle

Modifications du plan d'exécution Oracle SQL en raison de la conversion interne SYS_OP_C2C

SYS_OP_C2C est une internal function qui fait une implicit conversion de varchar2 au national character set en utilisant TO_NCHAR fonction. Ainsi, le filtre change complètement par rapport au filtre utilisant la comparaison normale.

Je ne suis pas sûr de la raison pour laquelle le nombre de lignes est inférieur , mais je peux vous garantir que cela pourrait être plus aussi. L'estimation des coûts ne sera pas affectée.

Essayons de voir étape par étape dans un cas de test.

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>

Jusqu'ici tout va bien. Puisqu'il n'y a qu'une seule ligne avec la valeur "a10", l'optimiseur a estimé une ligne.

Voyons avec la conversion du jeu de caractères national.

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>

Que s'est-il passé ici? Nous pouvons voir filter(SYS_OP_C2C("COL")=U'a10') , ce qui signifie qu'une fonction interne est appliquée et qu'elle convertit le varchar2 valeur à nvarchar2 . Le filtre a maintenant trouvé 10 lignes.

Cela supprimera également toute utilisation d'index, puisque maintenant une fonction est appliquée sur la colonne. Nous pouvons l'ajuster en créant un function-based index pour éviter le full table scan .

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>

Cependant, cela rendra-t-il les plans d'exécution similaires ? Non, je pense qu'avec deux jeux de caractères différents , le filtre ne sera pas appliqué de la même manière. Ainsi, la différence réside.

Mes recherches indiquent,