ORACLE中內部函數SYS_OP_C2C和隱式類型轉換


什么是SYS_OP_C2C呢?官方的介紹如下:

 

SYS_OP_C2C is an internal function which does an implicit conversion of varchar2 to national character set using TO_NCHAR function. Thus, the filter completely changes as compared to the filter using normal comparison.

 

 

簡單的來說,SYS_OP_C2C 是一個內部函數,功能是將VARCHAR2的數據類型轉換成國家字符集的NVARCHAR2類型,內部通過TO_NCHAR函數實現。

 

 

 

其實為什么要介紹一下這個內部函數,是因為最近一個同事在優化一個SQL語句時,發現即使創建了相關字段的索引,但是SQL語句的執行計划仍然不走索引,而走全表掃描,個人在分析了后,發現即使這個索引涉及的三個字段的選擇率不高,但是也不是不走索引的原因,而是因為隱式轉換問題(全局臨時表的跟物理表關聯的字段數據類型不一致),如果Automatic SQL Tuning - SQL Profiles Tuning Advisor建議創建基於SYS_OP_C2C的函數索引,或者執行計划中有類似 filter(SYS_OP_C2CCOLUMN).....這樣的信息,那么你應該檢查是否出現了隱式類型轉換(implicit type conversion

 

 

什么是隱式類型轉換(implicit type conversion)?

 

 

如果進行比較的兩個值的數據類型不同,則 ORACLE 必須將其中一個值進行類型轉換使其能夠比較。這就是所謂的隱式類型轉換。通常當開發人員將數字存儲在字符列時會導致這種問題的產生。ORACLE 在運行時會強制轉化其中一個值,(由於固定的規則)在索引字符列使用 to_number。由於添加函數到索引列所以導致索引不被使用。實際上,ORACLE 也只能這么做,類型轉換是一個應用程序設計因素。由於轉換是在每行都進行的,這會導致性能問題。詳見:

Document 232243.1 ORA-01722 ORA-01847 ORA-01839 or ORA-01858 From Queries with Dependent Predicates

 

 

官方文檔SYS_OP_C2C Causing Full Table/Index Scans (文檔 ID 732666.1)中有介紹:

 

APPLIES TO:

 

Oracle Database - Enterprise Edition - Version 10.1.0.2 to 12.1.0.1 [Release 10.1 to 12.1]

Information in this document applies to any platform.

This problem can occur on any platform.

 

SYMPTOMS

 

1) You are executing a query using bind variables.

2) The binding occurs via an application (eg. .NET, J2EE ) using a "string" variable to bind.

3) The query is incorrectly performing a full table/index scan instead of an unique/range index scan. 

4) When looking at advanced explain plan, sqltxplain or 10053 trace, you notice that the "Predicate Information" shows is doing a "filter(SYS_OP_C2C)".

 

e.g select * from table(dbms_xplan.display_cursor(&sql_id,null,'ADVANCED'));

 

Predicate Information (identified by operation id):

---------------------------------------------------

1 - filter(SYS_OP_C2C("COL1")=:B1)            <=== filter operation occurring

 

 

CAUSE

 

The bind variable "string" is using a different datatype to the column that is being queried. 

This means that an implicit conversion of the data is required to execute the query.  SYS_OP_C2C is the implicit function which is used to convert the column between nchar and char.

 

SOLUTION

 

  1. Create a function based index on the column.

e.g create index <index_name> on <table_name> (SYS_OP_C2C(<column>));

OR

  2. Ensure that your bind "string" datatype and column datatype are the same.

      A java example where this can occurs is when defaultNChar=TRUE.  This will cause strings to bind as NVARCHAR2 causing the predicate that are subset datatypes to be converted to NVARCHAR2.

      e.g.    -Doracle.jdbc.defaultNChar=true

                <connection-property name="defaultNChar">true</connection-property>

 

 

  

關於SYS_OP_C2C內部函數出現的可能原因,概況起來就是

 

1)正在執行一個帶有綁定變量的查詢

 

    關於這個,以前也曾經遇到過這樣的案例,參考這篇博文ORACLE綁定變量隱式轉換導致性能問題

 

2)綁定變量經由application.NET, J2EE等)使用 "string" 類型的綁定變量來綁定。

 

3)該查詢錯誤的執行了全表掃描/索引掃描,而沒有使用索引唯一掃描或者索引范圍掃描

 

4)使用advanced 選項查看explain plan, sqltxlain or 10053 trace,你會注意到在"Predicate Information"部分  會顯示一個 "filter(SYS_OP_C2C)".

 

 

解決方案:

 

1. 建立一個基於函數的索引。

 

e.g create index <index_name> on <table_name> (SYS_OP_C2C(<column>));

 

2. 讓綁定變量定義的數據類型與該列的數據類型一致。

 

 

 

 

參考資料:

 

https://hoopercharles.wordpress.com/2015/02/08/to-n-or-not-to-n-is-sys_op_c2c-the-question-oracle-nvarchar-slow/

SYS_OP_C2C Causing Full Table/Index Scans (文檔 ID 732666.1)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM