文章归档

表空间中的基于”xxxx.xxxx”的temporary对象说明与测试.

在创建大的索引,或者Rebuild大的索引以及使用CTAS创建大表,move大表的时候,我们经常可以看到一些纯粹数字表示(如”xxxx.xxxxx”)的类型为“TEMPORARY”的segment.之前我一直不清楚里面的两个数字是什么意思,曾经怀疑其与将要创建的object_id有某种关系, 前两天在 http://aprakash.wordpress.com/看到一个blog,说里面的数字是”filenumber.header_HEADERBLOCKNUMBER”,并且提供了比较详细的例子. 经过在我在测试环境的测试, 我觉得其更应该被表述为”header_file_number.header_block_number”.

在此特别感谢Anand与Hemant. 这篇文章的主要思想都是来自两位..

Segment name – Numeric
TEMPORARY Segments in Data/Index Tablespaces

1. 在Session 1中创建一个相对较大的表temp_obj. 同时在session 2中监控相应信息.

–Session 1>
09:30:52 SQL>
09:30:52 SQL> create table temp_obj tablespace users as
09:31:04 2 select a.*
09:31:04 3 from dba_objects a,dba_objects b
09:31:04 4 where rownum

–Session 2
09:30:56 SQL> l
1 select owner,segment_name,segment_type,header_file,header_block,blocks
[...]

关于index_equal index_join index_combine

今天下午部门一个兄弟做了一个关于index_join与injdex_combine区别的测试,引发我的兴趣, 找到一段Jonathan lewis在论坛的回复,简单翻译了下,并针对同事提供的说明做了一点补充与测试..

补充:刚刚看到Jonathan Lewis还有另外一篇关于index Combine的文章

http://nixforums.org/about109312-Hints-difference-between-AND_EQUAL–INDEX_JOIN-and-INDEX_.html
AND_EQUAL:

Can operate on 2 to 5 non-unique, single-column indexes with an equality condition on the indexed values. For colX = const each index produces a list of rowids which are guaranteed to be in rowid order, hence pre-sorted and ready for a merge join. rowids that survive the join are used [...]

最佳字段顺序-数据库物理设计

附注: 摘录自我翻译的《Oracle性能优化艺术》
很少有人关心如何寻找一个表的最佳字段顺序。根据环境的不同,可能一点影响也没有,也可能产生很大的开销。为了理解在哪些情形下可能带来很大的开销,必须先理解数据库引擎是如何将数据保存到数据块中的。
保存到数据块中的记录有个非常简单的结构(查看图12-1)。首先,会有一个头(H)记录这条记录的一些基本属性,诸如是否被锁住或者包含多少个字段。其次,就是它的字段。由于每个字段可能有不同的大小,所以每个字段包含两个部分。前一部分是数据的长度(Ln)。后一部分是数据本身(Dn)。

图12-1 存储在数据库库块中每一行记录的格式(H=行头,Ln=字段n的长度,Dn=字段n的数据)
理解这个格式的关键是,数据库引擎不知道一条记录中每个字段的偏移量(offset)。例如,如果需要定位字段3,必须从字段1开始。接着根据字段1的长度来定位字段2。最后,根据字段2的长度来定位字段3。因此,无论何时一条含有多个字段的记录,靠近记录开始的地方的字段定位的速度会明显快于靠近记录末尾的字段。为了更好地理解这一点,你可以运行脚本column_order.sql来进行测试,以估算搜索一个字段的额外开销。

(1) 创建一个包含250个字段的表:
create table t (n1 number,n2 number,….,n249 number,n250 number);
(2) 插入1万条记录。每条记录的每个字段都保存同样的内容。
(3) 估算下面这条语句的响应时间,针对这个表的每个字段执行一下下面的语句,一个循环执行1千次。
select count(colx) from t

图12-2概括了我的测试服务器运行这个测试的结果。特别要强调的是,引用第一个字段(位置1)的SQL语句的执行速度差不多是引用最后一个字段(位置 250)的执行速度的5倍。这是因为数据库引擎优化了每一个访问,从而避免了定位以及读出不需要处理的字段。例如,查询语句SELECT count(n3) FROM t在定位到第三个字段之后就停止了对记录的访问。图12-2也显示,在位置0,也就是查询count(*),任何字段都不需要访问。
图12-2 字段在记录中的位置和访问它需要的响应时间
由于这个原因,一般的规则是将访问频繁的字段放在前面。为了利用这一点,需要仔细确认只访问(引用)真正需要的字段。无论如何,从性能的角度看,查询不需要的字段(或者更甚,使用SELECT *引用所有的字段,即使事实上只有几个字段被应用程序使用,很遗憾,这种事经常发生)都是不好的,不仅是因为当从数据块中读出时会有额外开销,而且是因为在服务器端和客户端都需要分配更多的内存来临时保存这些数据,以及需要更多的时间和资源来通过网络传输这些数据,简单来讲,就是只要数据被处理,就会带来开销。
实际操作中,与字段顺序相关的额外开销在下面几种情况中(更加)显而易见。

当一张表包含大量的字段,并且SQL语句经常访问记录后面的很少几个字段。
当从同一个数据块中读取很多记录时,比如在做全表扫描的时候。这是因为,定位并访问一个数据块的开销要比定位并访问字段(只读取几条记录)时的开销多很多。

由于末尾的NULL值是不保存的,所以将可能包含NULL值的字段放在表的末端是合适的。这样,实际存储的物理字段数量以及相应的行的平均大小也可能降低。

delayed segment creation功能(11gr2新特性).

—-对于普通表以及其上的索引/lob segment/lob index等对象的segment,,在表中没有记录的时候,

—-segment 是先不创建的. 只有等到这个表中产生真实的记录的时候, 才会真正生成对应的segment. (见test 1).

但是要注意,,

上有1条记录,,哪怕是不涉及到对应的索引/lob项, segment也会创建..(见test 2).
分区表只要创建就会生成对应的segment, 也就是对于分区表, Oracle不支持这个特性 (见test 3, 附相关文档说明).

Restrictions on Deferred Segment Creation This clause is subject to the following restrictions:

You cannot defer segment creation for the following types of tables: partitioned tables, index-organized tables, clustered tables, global temporary tables, session-specific temporary tables, internal tables, typed tables, AQ tables, [...]

关于ORA-01450错误的一点测试与说明.

昨天team这边有个兄弟遇到错误ORA-01450: “maximum key length (6398) exceeded, 这个错误的发生主要是因为Oracle的index实现中一个index key不能同时跨越多个block, 详细描述可以参考Jonathan Lewis的online-rebuild 以及metalin的notes 136158.1.

This index key size is limited by the value of db_block_size, because a key value may not span multiple blocks. In fact, it is required that any index block must contain at least TWO index entries per block.

不过Metalink的note里面有一点错误, 也就是一个index block在oracle9i之后只要要能够放下一个index key就可以创建了.. 也就是在Oracle9i以后, [...]