SYS_OP_C2C
là một internal function
thực hiện implicit conversion
trong tổng số varchar2
thành national character set
sử dụng TO_NCHAR
hàm số. Do đó, bộ lọc thay đổi hoàn toàn so với bộ lọc sử dụng so sánh thông thường.
Tôi không chắc về lý do tại sao số lượng hàng lại ít hơn , nhưng tôi có thể đảm bảo rằng nó có thể còn nhiều hơn nữa cũng vậy. Ước tính chi phí sẽ không bị ảnh hưởng.
Hãy thử xem từng bước trong một trường hợp thử nghiệm.
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>
Càng xa càng tốt. Vì chỉ có một hàng có giá trị là 'a10', trình tối ưu hóa đã ước tính một hàng.
Hãy xem với việc chuyển đổi bộ ký tự quốc gia.
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>
Điều gì đã xảy ra ở đây? Chúng ta có thể thấy filter(SYS_OP_C2C("COL")=U'a10')
, có nghĩa là một hàm nội bộ được áp dụng và nó chuyển đổi varchar2
giá trị thành nvarchar2
. Bộ lọc hiện đã tìm thấy 10 hàng.
Điều này cũng sẽ ngăn chặn bất kỳ việc sử dụng chỉ mục nào, vì bây giờ một hàm được áp dụng trên cột. Chúng tôi có thể điều chỉnh nó bằng cách tạo một function-based index
để tránh 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>
Tuy nhiên, điều này sẽ làm cho các kế hoạch thực hiện tương tự? Không. Tôi nghĩ với hai bộ ký tự khác nhau , bộ lọc sẽ không được áp dụng giống nhau. Do đó, sự khác biệt nằm ở chỗ.
Nghiên cứu của tôi cho biết,