1        什么是隐式转换

当源数据的类型和目标数据的类型不同的时候,如果没有转换函数,就会发生隐式转换,也称自动转换。当然,

有些情况下有些类型是不可以发生转换的,比如说从DATE类型转换到NUMBER类型就会报错。

2        什么场景会发生隐式转换

在oracle中,如果不同的数据类型之间关联,如果不显式转换数据,则它会根据以下规则对数据进行隐式转换

1)      比较时,一般是字符型转换为数值型,字符型转换为日期型

2)      算术运算时,一般把字符型转换为数值型,字符型转换为日期型

3)      连接时(||),一般是把数值型转换为字符型,日期型转换为字符型

4)      赋值、调用函数时,以定义的变量类型为准。

3        为什么要避免隐式转换

隐式转换的缺点:

1)      使用显示类型转换会让我们的SQL更加容易被理解,也就是可读性更强,但是隐式类型转换却没有这个优点。

2)      隐式类型转换往往对性能产生不好的影响,特别是左值的类型被隐式转为了右值的类型。这种方式很可能使我们本来可以使用索引的而没有用上索引,也有可能会导致结果出错。

3)      隐式类型转换可能依赖于发生转换时的上下文环境,比如to_date(sysdate, fmt),一旦上下文环境改变,很可能我们的程序就不能运行。

4)      隐式类型转换的算法或规则,以后Oracle可能改变,这是很危险的,意味着旧的代码很可能在新的Oracle版本中运行出现问题(性能、错误等),显示类型转换总是有最高的优先级,所以显示类型转换没有这种版本更替可能带来的问题。

5)      隐式类型转换是要消耗时间的,当然同等的显式类型转换时间也差不多,最好的方法就是避免类似的转换,在显示类型转换上我们会看到,最好不要将左值进行类型转换,到时候有索引也用不上索引,还要建函数索引,索引储存和管理开销增大。

总结:

Oracle 使用数据类型的优先级来决定隐式类型转换,原则是将优先级低的转换为优先级高的。

隐式转换发生在字段列上时将使索引失效

随着公司业务的数据量的增加,在高并发和大吞吐量的场景下,隐式转换产生的性能问题会被千倍万倍的放大,将很有可能会导致系统崩塌或者交易崩溃,会造成很大的业务经济损失。

Oracle使用数据类型的优先级来决定自动类型转换,Oracle类型如下优先:
■ Datetime and interval 类型
■ BINARY_DOUBLE
■ BINARY_FLOAT
■ NUMBER
字符类型
■ 所有其它内置类型

4        如何判断SQL发生了隐式转换

在编写复杂SQL以后,一般要去走一下执行计划,查看一下整个SQL的性能,比如是否存在全表扫描,笛卡尔积,隐式转换问题。

隐式转换的关注点:

1.执行计划是否有internal_function()函数。

2.执行计划是否字段上多出了处理函数,比如to_number()

验证:minus

示例:A(原SQL,有隐式转换)-àB(改造后SQL)

(A minus B ) union all (B minus A)

(SELECT *

from l_loan_mas

WHERE TRUNC(LOAN_DATE) <=  TRUNC(SYSDATE - 100)

MINUS

select *

from l_loan_mas

WHERE LOAN_DATE <  TRUNC(SYSDATE - 99))

UNION ALL

(SELECT *

from l_loan_mas

WHERE TRUNC(LOAN_DATE) <=  TRUNC(SYSDATE - 100)

MINUS

select *

from l_loan_mas

WHERE LOAN_DATE <  TRUNC(SYSDATE - 99))

5        常见的隐式转换类型及修改方案

5.1       对时间字段做函数操作的时候发生的隐式转换:

5.1.1       有对时间进行格式化:

TO_CHAR(T.DATE_CREATED, 'yyyymmdd') = TO_CHAR(SYSDATE, 'yyyymmdd')

可以修改为如下:

T.DATE_CREATED < to_date(TO_CHAR(SYSDATE + 1, 'yyyymmdd'), 'yyyy/mm/dd')

and T.DATE_CREATED >= to_date(TO_CHAR(SYSDATE, 'yyyymmdd'), 'yyyy/mm/dd')

5.1.2       对时间字段操作函数,比较两边都是trunc取值 <=:

TRUNC(CREATED_DATE) <= TRUNC(SYSDATE - 5)

可修改为:

CREATED_DATE < TRUNC(SYSDATE - 4)

示例:

select *

from l_loan_mas

WHERE TRUNC(LOAN_DATE) <=  TRUNC(SYSDATE - 5);

修改后

select *

from l_loan_mas

WHERE LOAN_DATE < TRUNC(SYSDATE - 4);

5.1.3       对时间字段操作函数,比较两边都是trunc取值 =:

Trunc(E_CREATED) = Trunc (SYSDATE)

可修改为:

T.DATE_CREATED < trunc(SYSDATE + 1)

and T.DATE_CREATED >=trunc(SYSDATE)

实例:

SELECT LOAN_DATE

FROM L_LOAN_MAS

WHERE  Trunc( LOAN_DATE)   = Trunc (SYSDATE);

修改后方案

SELECT LOAN_DATE

FROM L_LOAN_MAS

WHERE  LOAN_DATE   <=trunc(SYSDATE + 1)

AND LOAN_DATE >trunc(SYSDATE);

5.1.4       时间字段操作函数,比较两边都是trunc取值 >=:

TRUNC(LLM.COMPLETED_DATE) >= TRUNC(sysdate, 'MM')

可以修改为:

LLM.COMPLETED_DATE >= TRUNC(sysdate, 'MM')

select appl_no,loan_date

from l_loan_mas

where trunc(loan_date) > =trunc(sysdate,'MM');

select appl_no,loan_date

from l_loan_mas

where loan_date > =trunc(sysdate,'MM');

5.1.5       对时间字段有ADD_MONTHS的操作如下:

TRUNC(T.DUE_DATE, 'mm') = ADD_MONTHS(TRUNC(:B1, 'mm'), -1)

可修改为:

T.DUE_DATE >= ADD_MONTHS(TRUNC(:B1, 'mm'), -1)

AND T.DUE_DATE< TRUNC(:B1, 'mm')

示例:

select appl_no,loan_date

from l_loan_mas

where trunc(loan_date) =ADD_MONTHS(TRUNC(sysdate, 'mm'), -1)

select appl_no,loan_date

from l_loan_mas

where loan_date >= ADD_MONTHS(TRUNC(sysdate, 'mm'), -1)

and loan_date < TRUNC(sysdate, 'mm')

5.1.6       时间函数,比较两边都是trunc取值 >:

TRUNC(FCD) > TRUNC(SYSDATE) – 3

可修改为:

FCD >= TRUNC(SYSDATE) – 2

示例:

select *

from l_loan_mas

WHERE TRUNC(LOAN_DATE)  > TRUNC(SYSDATE) -3;

select *

from l_loan_mas

WHERE LOAN_DATE  >= TRUNC(SYSDATE) -2

5.1.7       对时间字段的操作取月份差的例如:

floor(months_between(SYSDATE,loan_date)) >= 2

可以修改为:

loan_date <= add_months(SYSDATE, -2)

select *

from l_loan_mas

where floor(months_between(SYSDATE,loan_date)) >= 2

修改后

select *

from l_loan_mas

where loan_date <= add_months(SYSDATE, -2);

5.2       取值类型与字段类型不匹配

5.2.1       字段是varchar或者是char 而关系对等中是纯数字:例如下面

bank_flag = 1

可以修改为

bank_flag = ‘1’

示例:

l_loan_mas.loan_code字段为varchar类型

SELECT *

FROM l_loan_mas

WHERE loan_code = 44;

修改后

SELECT *

FROM l_loan_mas

WHERE loan_code = '44'

5.2.2       字段是number类型二传过来比较的值是string:

PK_SERIAL = :13 可以修改为  PK_SERIAL = to_number(:13)

示例:l_loan_mas.appl_amt类型 NUMBER(12,2)

SELECT appl_no,appl_amt

FROM l_loan_mas.appl_amt

WHERE appl_amt = '50000';

修改后

SELECT appl_no,appl_amt

FROM l_loan_mas

WHERE appl_amt = 50000;

5.2.3       两个字段关联,其中一个字段是number类型,另外一个是varchar类型:

UP_DEPT_CODE  VARCHAR2(12),PK_SERIAL   NUMBER number类型。

有如下关联时会发生隐式转换:UP_DEPT_CODE = PK_SERIAL

可以修改为:UP_DEPT_CODE = to_char(PK_SERIAL)

小结:

1.日期不要作操作。

2. 写=号时 两边类型一定要一致,不一致时需要显示转换。

DB性能-隐式转换的更多相关文章

  1. SQL Server中提前找到隐式转换提升性能的办法

        http://www.cnblogs.com/shanksgao/p/4254942.html 高兄这篇文章很好的谈论了由于数据隐式转换造成执行计划不准确,从而造成了死锁.那如果在事情出现之前 ...

  2. ORACLE绑定变量隐式转换导致性能问题

    年后一次系统升级后,监控数据库的工具DPA发现数据库的Total Wait时间突然飙增,如下截图所示,数据库的总体等待时间对比升级前飙增了非常多 另外就是发现出现了较多的等待事件,主要有latch: ...

  3. 关于ORACLE隐式转换后性能问题

    SELECT TM.MONEY_CODE FROM T_CONTRACT_MASTER T,T_MONEY TM WHERE T.MONEY_ID = TM.MONEY_ID AND T.POLICY ...

  4. MySQL性能优化:MySQL中的隐式转换造成的索引失效

    数据库优化是一个任重而道远的任务,想要做优化必须深入理解数据库的各种特性.在开发过程中我们经常会遇到一些原因很简单但造成的后果却很严重的疑难杂症,这类问题往往还不容易定位,排查费时费力最后发现是一个很 ...

  5. VB.Net隐式转换和显式转换的方法(转)

    VB.Net隐式转换和显式转换的方法(转) “隐式转换”不需要源代码中的任何特殊语法.在下面的示例中,在将 k 的值赋给 q 之前,Visual Basic 将该值隐式转换成单精度浮点值.   Dim ...

  6. Scala学习教程笔记三之函数式编程、集合操作、模式匹配、类型参数、隐式转换、Actor、

    1:Scala和Java的对比: 1.1:Scala中的函数是Java中完全没有的概念.因为Java是完全面向对象的编程语言,没有任何面向过程编程语言的特性,因此Java中的一等公民是类和对象,而且只 ...

  7. Spark记录-Scala程序例子(函数/List/match/option/泛型/隐式转换)

    object func { def main(args:Array[String]):Unit={ //函数赋值给变量时, 必须在函数后面加上空格和下划线. def sayHello(name: St ...

  8. 大数据技术之_16_Scala学习_06_面向对象编程-高级+隐式转换和隐式值

    第八章 面向对象编程-高级8.1 静态属性和静态方法8.1.1 静态属性-提出问题8.1.2 基本介绍8.1.3 伴生对象的快速入门8.1.4 伴生对象的小结8.1.5 最佳实践-使用伴生对象解决小孩 ...

  9. 9. Scala隐式转换和隐式值

    9.1 隐式转换 9.1.1 提出问题 先看一个案例演示,引出隐式转换的实际需要=>指定某些数据类型的相互转化 object boke_demo01 { def main(args: Array ...

随机推荐

  1. opencv-python教程学习系列9-程序性能检测及优化

    前言 opencv-python教程学习系列记录学习python-opencv过程的点滴,本文主要介绍程序性能检测及优化,坚持学习,共同进步. 系列教程参照OpenCV-Python中文教程: 系统环 ...

  2. Executor 框架详解

    框架最核心的类是ThreadPoolExecutor,它是Java线程池的实现类,通过Executors工具类,可以创建3种类型的ThreadPoolExecutor: 首先附上ThreadPoolE ...

  3. HDU 1024:Max Sum Plus Plus(DP,最大m子段和)

    Max Sum Plus Plus Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others ...

  4. 51Nod:活动安排问题之二(贪心)

    有若干个活动,第i个开始时间和结束时间是[Si,fi),同一个教室安排的活动之间不能交叠,求要安排所有活动,最少需要几个室? 输入 第一行一个正整数n (n <= 10000)代表活动的个数. ...

  5. 习题3.5 求链表的倒数第m个元素(20 分)浙大版《数据结构(第2版)》题目集

    请设计时间和空间上都尽可能高效的算法,在不改变链表的前提下,求链式存储的线性表的倒数第m(>0)个元素. 函数接口定义: ElementType Find( List L, int m ); 其 ...

  6. 字符串的比较【string和字符数组】

    无论是string 还是 字符数组的字符串比较函数,返回的都是字典序的大小.如 1234 和 5 比较时就是1234的字典序小于5,要想比较字符串表示的数字的大小,需要自己写函数比较

  7. laravel5.3 源码分析 Passport

    laravel5.3,密码模式的授权认证过程.我会通过两部分内容分享以及查看passport的认证流程分享出来 第一部分:根据官方文档,通过Composer安装Passport 文档地址:http:/ ...

  8. mysql 变量名称的使用不当的一个错误

    对于开发来说重要的是按照规范进行开发. 昨天自己在进行开发测试的时候,编写mysql 的一个存储过程 ,代码是比较简单的 就是根据名称查询对应的数据并返回 DELIMITER // CREATE PR ...

  9. c#数据库訪问返回值类型为SqlDataReader时使用using时注意的问题

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/u010512579/article/details/24011761 在封装通用 SQLSERVER ...

  10. 调试 FastAdmin 出现 Failed to parse SourceMap

    看到群里有人说在调试 FastAdmin出现 SourceMap 出错. 报错信息为: Failed to parse SourceMap 来自 Karson 说明: 这个文件是用于匹配原有less中 ...