Ответ 1
SYS_OP_C2C
- это internal function
, который выполняет implicit conversion
от varchar2
до national character set
с помощью функции TO_NCHAR
. Таким образом, фильтр полностью изменяется по сравнению с фильтром, используя нормальное сравнение.
Я не уверен, почему количество строк меньше, но я могу гарантировать, что это может быть больше. Оценка стоимости не будет затронута.
Попробуйте увидеть шаг за шагом в тестовом примере.
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>
Пока все хорошо. Поскольку существует только одна строка со значением "a10", оптимизатор оценивает одну строку.
Посмотрите с преобразованием национальных символов.
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>
Что здесь произошло? Мы можем видеть filter(SYS_OP_C2C("COL")=U'a10')
, что означает, что применяется внутренняя функция, и она преобразует значение varchar2
в nvarchar2
. Фильтр теперь нашел 10 строк.
Это также подавляет любое использование индекса, так как теперь функция применяется к столбцу. Мы можем настроить его, создав function-based index
, чтобы избежать 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>
Однако будет ли подобное выполнение планов выполнения? Нет. Я думаю, что с двумя разными символами фильтр не будет применяться одинаково. Таким образом, разница лежит.
В моих исследованиях говорится,
Обычно такие сценарии возникают, когда данные, поступающие через приложение Тип nvarchar2, но столбец таблицы varchar2. Таким образом, Oracle применяет внутреннюю функцию в работе фильтра. Мое предложение чтобы хорошо знать ваши данные, чтобы вы использовали похожие типы данных во время этап проектирования.