什么是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_C2C(COLUMN).....”这样的信息,那么你应该检查是否出现了隐式类型转换(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)

ORACLE中内部函数SYS_OP_C2C和隐式类型转换的更多相关文章

  1. C++ 中operator用法:隐式类型转换

    [转]C++ operator两种用法 C++,有时它的确是个耐玩的东东,就比如operator,它有两种用法,一种是operator overloading(操作符重载),一种是operator c ...

  2. ORACLE隐式类型转换

      隐式类型转换简介   通常ORACLE数据库存在显式类型转换(Explicit Datatype Conversion)和隐式类型转换(Implicit Datatype Conversion)两 ...

  3. Qt 中C++ static_cast 和 reinterpret_cast的区别(static_cast是隐式类型转换,会有数据损失,reinterpret_cast是底层二进制转换,没有数据损失)

    1.C++中的static_cast执行非多态的转换,用于代替C中通常的转换操作.因此,被做为隐式类型转换使用.比如: int i; float f = 166.7f; i = static_cast ...

  4. js隐式类型转换,预编译、递归、作用域,作用域链、闭包、立即执行函数、继承圣杯模式

    隐式类型转换 调用Number()当有运算符(加减乘除,求余)时,会调用Number()转为数字再运算,除了 加 当 有字符串时就变身成拼接Boolean();String(); typeof()st ...

  5. js条件判断时隐式类型转换

    Javascript 中,数字 0 为假,非0 均为真 在条件判断运算 == 中的转换规则是这样的: 如果比较的两者中有布尔值(Boolean),会把 Boolean 先转换为对应的 Number,即 ...

  6. dynamic_cast 和 static_cast 隐式类型转换的区别

    首先回顾一下C++类型转换: C++类型转换分为:隐式类型转换和显式类型转换 第1部分. 隐式类型转换 又称为“标准转换”,包括以下几种情况:1) 算术转换(Arithmetic conversion ...

  7. c++ operator操作符的两种用法:重载和隐式类型转换,string转其他基本数据类型的简洁实现string_cast

    C++中的operator主要有两个作用,一是操作符的重载,一是自定义对象类型的隐式转换.对于操作符的重载,许多人都不陌生,但是估计不少人都不太熟悉operator的第二种用法,即自定义对象类型的隐式 ...

  8. C++的隐式类型转换与转换操作符

    C++标准允许隐式类型转换,即对特定的类,在特定条件下,某些参数或变量将隐形转换成类对象(创建临时对象).如果这种转换代价很大(调用类的构造函数),隐式转换将影响性能.隐式转换的发生条件:函数调用中, ...

  9. C++的隐式类型转换

    C++是一种复杂的语言,其中有许多“好玩”的特性,学习C++的过程就像在海边捡一颗颗石头,只要坚持不懈,也许一颗颗小石头也能建起你自己小小的城堡. 废话完后,讲讲自己捡到的石头:隐式类型转换 学习出处 ...

随机推荐

  1. 导入项目报错【Minimum supported Gradle version is 3.3. Current version is 2.14.1】

    问题描述 导入项目的时候,因为同事的开发环境是Android Studio 2.3.2  Gradle3.3.而我的开发环境是Android Studio 2.2.2 Gradle2.14.1. 所以 ...

  2. Net使用RdKafka引发异常RdKafka.Internal.LibRdKafka 的类型初始值设定项引发异常

    在Net中VS2015用RdKafka组件开发消息发布和消费,引发下面的异常 RdKafka.Internal.LibRdKafka 的类型初始值设定项引发异常System.TypeInitializ ...

  3. 13 Tensorflow机制(翻译)

    代码: tensorflow/examples/tutorials/mnist/ 本文的目的是来展示如何使用Tensorflow训练和评估手写数字识别问题.本文的观众是那些对使用Tensorflow进 ...

  4. HttpServetRequest读取body只能一次的问题

    HTTP请求中的是字符串数据: //字符串读取 void charReader(HttpServletRequest request) { BufferedReader br = request.ge ...

  5. Spring Boot (五)Spring Data JPA 操作 MySQL 8

    一.Spring Data JPA 介绍 JPA(Java Persistence API)Java持久化API,是 Java 持久化的标准规范,Hibernate是持久化规范的技术实现,而Sprin ...

  6. Linux录制、回放和共享终端操作

    另一篇终端会话共享的文章:Linux终端会话实时共享(kibitz) 使用script命令录制,使用scriptreplay播放录制的操作.共享终端的操作,则需要使用命名管道来实现. 1.1 录制 [ ...

  7. python理解描述符(descriptor)

    Descriptor基础 python中的描述符可以用来定义触发自动执行的代码,它像是一个对象属性操作(访问.赋值.删除)的代理类一样.前面介绍过的property是描述符的一种. 大致流程是这样的: ...

  8. c#中的特性Attribute

    一:特性是什么?特性怎么创建怎么使用? 这一章节,我想谈谈c#的特性方面的知识,特性大家在工作开发中都很熟悉,比如我们经常见到的 1:key Display --EF 2:Import 3:HttpG ...

  9. 解码 id_token

    简介 id_token是一个特殊的token,在Microsoft Graph的认证和授权过程中颁发,它包含了已认证用户的一些信息.本文将介绍如何通过实例理解id_token,并且演示了如何解码. 准 ...

  10. mybatis_03_ mapper代理方式实现MyBatis的Dao编写

    不是用mapper代理方式也能够实现,但是不推荐 Mapper代理的开发方式,程序员只需要编写mapper接口(相当于dao接口)即可.Mybatis会自动的为mapper接口生成动态代理实现类. 不 ...