Database

Oracle中 To_Date 函数 的用法

to_date(‘2003/07/09’, ‘yyyy/mm/dd’)  would return a date value of July 9, 2003. to_date(‘070903’, ‘MMDDYY’) would return a date value of July 9, 2003. to_date(‘20020315’, ‘yyyymmdd’) would return a date value of Mar 15, 2002. See `http://www.techonthenet.com/oracle/functions/to_date.php

软解析、硬解析及其对性能的影响

SQL解析时要经历以下几个步骤:    1. VPD相关处理    2. 语法、语义、权限检查    3. 对SQL进行逻辑优化    4. 再进行物理优化 这其中会牵涉到游标的缓存读写: 看下缓存里有没有所需的游标,有就读出来直接用,没有就要创建一个出来用,用完后塞到缓存中。 如果缓存已存在,那就只需执行上面的步骤#1和步骤#2。 这就是软解析。 否则,就会执行所有步骤。这就是硬解析。 由于步骤#3和#4比较耗费CPU,而在缓存里创建新游标又比较耗内存,因此硬解析比软解析的开销要大很多,因此应该尽量避免硬解析。 要避免硬解析,就得尽量重用缓存中的游标。而游标是以SQL为Key的,要重用游标,就要尽量对同样的操作使用同样的SQL(大小写、空格都要一样),也就是说要用Bind Variables. ============================================================ 不过,软硬解析代价都其实都很高,因为它们都会产生对共享资源的竞争使用。 Oracle中,这些操作的并发性达到了“可串行化”级别,对性能的影响很大。

倒底要不要使用Bind Variables

为了避免硬解析(即为了实现游标缓存),应该使用Bind Variables。这点大家都知道。 然而, Bind Variables如果出现在where子句中,它就会减弱查询优化器的某种能力:根据统计信息和SQL中的字面量选择最优的执行计划。  比如说,假定当前表里的age大都是50岁以下。如果SQL里指定了按 age<50 来查询,那优化器就会来一个全表扫描,快速返回相应数据; 如果SQL里使用的是 age < :age1,那优化器就不敢轻易走全表扫描了 (11g里部分地解决了这个问题,在此不表)。 那倒底要不要用Bind Variables呢? 《Troubleshooting Oracle Performance》给出的方案是:   1. 如果Bind Variable并没有出现where子句,那就没有理由不用它   2. 在小量数据查询环境下,如 OLTP中,硬解析的时间与执行时间相当甚至更大, 应该使用Bind Variable,避免硬解析   3. 在大量数据查询环境下,如 OLAP中,硬解析的时间与执行时间相比只是一个零头, 这时就应用直接用字面量,以免查询优化器选错了执行计划。

怎样理解执行计划?

待完善… The output may look like,    Operation | Options | Object Name | Cost | Cardinality | Bytes Operation, Options: 数据库在这一步采取的操作及其使用的参数. 请参考 所有操作的集合 Object Name: Name of the table or index. Cost:  a function of the CPU_COST and IO_COST. 它是无量纲的,仅用于各步操作的代价比较 Cardinality: the number of rows accessed by the operation Bytes:   the number of bytes …

怎样理解执行计划? Read More »

Notes on ‘Expert Oracle’ — No.12.2: 数据类型 — 数字类型

1.一般都用"Number"这个类型 2.数据库如何处理精度超出定义的输入数据?   a.舍入: 小数位过多,但整数位未超标,则为小数位作四舍五入并插入数据库   b.拒绝并报错: 整数位若超标,则直接拒绝 3.Number类型 V.S. Float/Double类型   a.Number类型更准确   b.在做数学计算时,Float/Double的性能更高,因为它是基于硬件的计算,而Number是基于软件的计算。不过Float/Double数学计算的准确度较差。   c.可以将字段存为Number类型,在需要数学计算时,临时cast为Float/Double类型

Notes on ‘Expert Oracle’ — No.12.3: 数据类型 — Date/Time类型

1.查询时,尽量避免在日期类型的字段上使用函数    a.因为这会使该字段上的索引失效。比如说         坏:select … where to_char(birthday) = ‘2010-1-1’         好:select … where birthday     = to_date(‘2010-1-1’)    b.如果非用不可,可以考虑一下是不是可以不用 to_char,而只用 trunc就可以了?因为trunc函数的性能要好得多。比如说,        坏: select … where to_char(birthday, ‘YYYY’) = ‘2005’        好: select … where trunc(birthday, ‘y’) = to_date(‘1-1-2005’) 2. Date V.S. Timestamp      Date只能精确到“秒”    而Timestamp可以精确到 10的-9次方秒

Notes on ‘Expert Oracle’ — No.13.1: 分区 — 分区的好处

1.提高系统的可靠性(HA): 不把所有的鸡蛋放到同一个篮子里    a.分区A坏了,但分区的B数据仍然可以被查询到    b.分区A坏了,恢复这个分区的时间比恢得整张表的时间要短得多 2.减少管理负担。 比如说,重建某个分区的索引比重建整张表的索引要轻松的多 3.SQL的性能    a.在较早版本的Oracle中,想要执行“PDML”(一种并行执行DML的机制),就必须对表进行分区    b.可以提升OLAP系统的查询。 因为OLAP的查询一般都是大批量查询,不用索引,而是进行“全面扫描”。分区前,需要全表扫描;分区后,可能只需对某一个区进行全面扫描。    b.基本不能提升OLTP系统的查询速度,甚至可能更慢。       i.查询基于索引。分区前,在大索引中查询;分区后,在小索引中查询。这两种查询的速度是一样的。      ii.甚至可能更慢。因为现在可能要查好几个索引,产生更多I/O。    c.对OLTP的DML操作可能有好处       i.因为这样可以减少数据竞争和索引竞争的机率      ii.但是仍有额外开销:插入新行时,需要判断把它放在哪个分区。

Notes on ‘Expert Oracle’ — No.13.2: 分区 — 分区机制

Q:按什么分区呢? A:四种方案    1.按数值区间分。如 [1-100]放A区,[101-200]放B区    2.按枚举值对离散值进行分区,如 [江西,福建] 放A区,[北京,浙江]放B区。 这叫“列表分区”    3.直接按散列值分区。这没啥好说的。    4.综合使用以上几种分区机制进行多次分区,在大分区里再分成小分区。 Q:数据不会在分区之间迁移吧? A:会。    1.比如 原来有条记录值为 1,放在A区;现在它的值变成了105,就必须移到B区了。    2.这种“行移动”的开销很大。如果你选择的分机机制导致这种事情经常发生,那就是失败的分区

Notes on ‘Expert Oracle’ — No.13.3: 分区 — 索引分区

索引分区的两种模式    1.表分区 =>相应地 索引分区。表分区A对应索引分区A,表分区B对应索引分区B。这叫“局部索引分区”    2.独立于表分区,对索引进行分区。 分区以后,索引分区A中可能既有 表分区A某些行的条目,又有表分区B某些行的条目; 同样,表分区A中可能有些数据的条目在索引分区A中,又有些数据的条目在索引分区B中。 这叫“全局索引分区”

Notes on ‘Expert Oracle’ — No.12.1: 数据类型 — 字符类型

1.注意字符集的设置,即NLS 2.char/nchar根本就用不上   i.它会通过空格填补空余空间,造成空间浪费 ii.它还会导致  select … where column_five_char = ‘ABC’ 打不到记录,因为 数据库里存的不是 ‘ABC’,而是 ‘ABC  ‘ 3.设置varhcar2的宽度时要注意:宽度有两种单位,一为 byte 类型,另一为 char 类型    在非西文应用中,可以使用 char作为宽度单位,因为你的需要注一般是 “姓名不能超过50字符”,而不是“姓名不能超过50字节” 4.如果用 nvarchar2的话,那它的宽度单位固定为 char