Archive for November, 2011
解析Oracle rowid系列一
搞Oracle的人,都知道表里有一个叫做rowid的伪列,也知道可以通过rowid来快速定位表里的记录,至少通过oracle的索引来快速查找表里的数据就是通过rowid来定位的。可是,我们真的对rowid很了解吗?至少,我之前存在了一些误区,甚至有点儿荒谬!在此,对rowid作一个全面解析,同大家分享,以飨网友。
1 Oracle rowid格式:
Oracle rowid format
rowid
OOOOOO
FFF
BBBBBB
RRR
说明
数据对象号
相对文件号
数据块号
行号
上述表格是Oracle 9i及以上版本数据库中的rowid格式:6位对象号+3位相对文件号+6位数据块号+3位行号,是一个18位的64进制值。这个18位的64进制值在数据库内却是以10个bytes合计80个bit的二进制数存放的,和我们直接看到的结果有所区别。这里的64进制和10进制的对应编码如下表:
64进制-10进制转换表
64进制编码
A
B
…
Z
a
b
…
z
0
1
…
9
+
/
10进制值
0
1
…
25
26
27
…
51
52
53
…
61
62
63
2 那么这个18位的64进制值又是如何同80位的二进制数对应的呢?其中,6位的对象号在数据库中是用32位二进制来存放的,也就意味着一个oracle数据库中最多可以有232个对象,即4G个对象;3位的相对文件号在数据库中是用10位二进制来存放的,也就意味着一个表空间中最多可以容纳210=1024去掉全0和全1个数据文件,即1022个数据文件;6位的数据块号用22位二进制来存放的,也就意味着一个数据文件最多可以包含222=4M个数据块;3位的行号在数据库中是用16位二进制来存放的,也就意味着一个数据块上最多可以容纳216=65536行记录。
3 我们已经对rowid有了基本认识,我们又该如何获取rowid呢?见下例:
SQL> show user;
USER is “HR”
SQL> select employee_id,last_name,rowid from employees where employee_id=100;
EMPLOYEE_ID LAST_NAME ROWID
———– ————————- ——————
100 King AAAR5pAAFAAAADPAAA
SQL>
我们可以在查询列表中,把rowid伪列当做普通的字段来查询。上例中,AAAR5p就是HR.employees在数据库中的对象号,AAF表示相对文件号,AAAADP则表示数据块编号,最后的3个AAA则表示行号。当然,我们完全可以根据上述的转换表,将这些64进制值直接转成对应的10进制值。分别就是HR.employees表在数据库内的对象号是73321,而该表在数据库内部是存放在第5号文件(AAF=0*642+0*641+5*640=5)上的,employee_id=100的记录则是放在第5号文件的第207个数据块上的;最后的AAA表示该记录是位于第5号文件上的第207个数据块上的第1条记录。
4 除了上述方法,我们还可以通过数据库提供给我们的工具包来获取该信息:
SQL> select rowid,
2 dbms_rowid.rowid_object(rowid) object_id,
3 dbms_rowid.rowid_relative_fno(rowid) file_id,
4 dbms_rowid.rowid_block_number(rowid) block_id ,
5 dbms_rowid.rowid_row_number(rowid) num ,
6 rowidtochar(rowid) from employees where employee_id=100
7 ;
ROWID OBJECT_ID FILE_ID BLOCK_ID NUM ROWIDTOCHAR(ROWID)
—————— ———- ———- ———- ———- ——————
AAAR5pAAFAAAADPAAA [...]
游泳卡免费赠送
近日来,厦门的天气不太正常,突然有点儿夏天的感觉,就想起之前在厦门佳健游泳馆办的那张会员卡,一再申请LP前去游泳未果,只好屁颠屁颠儿的一个人在上个周末游了两次,感觉挺舒服,缓解了疲劳,活动了颈椎。
只是,那张游泳卡是2011年11月30日就到期了,截止目前还有14次未用,估计自己是消费不完了。在此,向各位互联网的朋友们免费赠送出去,如果有需要的,可以及时回复我,或转至About页面获取我的联系方式。
友情提醒读者:
1 工作之余,加强锻炼身体,尤其是IT同行,长期坐立工作,易患职业病;
2 季节变换,天气变化,尤其是厦门这几天的温度变化明显,注意保暖;
3 如需要免费游泳卡的请从速,这个月30号就到期了,或者友情转发本文;
4 直接联系我就成,别不好意思,我很爽快的。
下载本文的PDF版本, 方便离线阅读转载
Oracle 11g Concepts 笔记3:什么是B树索引及其介绍
在上一篇笔记里我们简单了解了Oracle索引的分类及唯一索引的特征,在本篇里我们简单了解什么是B-Tree Indexes及对其作一基本介绍。
B-trees, short for balanced trees, are the most common type of database index.顾名思义,B-Tree是一个平衡树的结构【注意这里的B表示Balanced平衡的意思,而不是Binary二叉】,B树索引也是Oracle里最为常见的索引类型。B树索引里的数据是已经按照键字或者是被索引字段事先排好序存放的,默认是升序存放,也解释了为什么我们在创建索引的时候有可能会用到数据库的临时表空间的临时段。下面,看一幅B树索引的内部结构图:
对于这幅B树存储结构图作以下几点介绍:
1 索引高度是指从根块到达叶子块时所遍历的数据块的个数,而索引层次=索引高度-1;本图中的索引的高度是3,索引层次等于2;通常,索引的高度是2或者3,即使表中有上百万条记录,也就意味着,从索引中定位一个键字只需要2或3次I/O,索引越高,性能越差;
2 B树索引包含两种数据块儿:分枝块(Branch Block)和叶子块(Leaf Block);
3 分枝块里存放指向下级分枝块(索引高度大于2,即有超过两层分枝块的情况)或者直接指向叶子块的指针(索引高度等于2,即层次为1的索引);
4 叶子块,就是位于B树结构里最底层的数据块。叶子块里存放的是索引条目,即索引关键字和rowid,rowid用来精确定位表里的记录;索引条目都是按照索引关键字+rowid已经排好序存放的;同一个叶子块里的索引条目同时又和左右兄弟条目形成链表,并且是一个双向链表;
5 B树索引的所有叶子块一定位于同一层上,这是由B树的数据结构定义的。因此,从根块到达任何一个叶子块的遍历代价都是相同的;
下载本文的PDF版本, 方便离线阅读转载
Oracle 11g Concepts 笔记2:什么是唯一、非唯一索引及索引分类
从Oracle索引的特征上,我们可以简单的把索引分为Unique Indexes and Nonunique Indexes,即唯一索引和非唯一索引。
1 对于唯一索引,唯一索引确保被索引的字段或多个联合字段在表中绝对不会有重复值;通常,我们在建表时,创建唯一约束或者主键约束,再或者建表以后给表添加唯一、主键约束时,Oracle会自动在主键、唯一约束的字段上创建唯一索引,并且索引的名字跟约束的名字一样,如:
SQL> create table tt(id1 number primary key,id2 number,id3 number);
Table created.
SQL> select index_name,table_name,uniqueness from user_indexes where table_name=’TT’;
INDEX_NAME TABLE_NAME [...]
WordPress恢复及建站记
前段时间,经过几番折腾终于将个人Blog,OracleOnLinux.cn从以前的备份数据中完全恢复过来,历经将长达半年的临时无法访问后,终于可以正常访问了。
工作之余,抽点儿时间简单记录这次恢复经过及Blog建站过程。
首先记录建站过程:
2008年10月3日花1元RMB,以个人名义成功在紫田网络注册域名 www.OracleOnLinux.cn,至今一直生效,并准备长期使用下去;
2009年10月9日,在好友Jia GuoQing免费提供空间及相关技术的大力支持下,成功搭建WordPress个人Blog,第一篇系统日志Hello World面世,此时离域名生效日期已经1年有余;
期间,由于个人懒惰+不勤奋+不坚持等种种原因,博客更新频率颇低,站点流量徘徊不前;
2011年5月25日,在空间服务器崩溃前发表最后一篇博文:记一次10g RAC收缩表空间;
之后的某一天,国庆兄告之我,空间服务器硬盘故障,导致数据丢失,好在之前用PHPMyAdmin对后台的MySQL数据库做了一次完全备份,生成了一份SQL的dump文件,身为Oracle DBA的我想,只要有有效的备份,恢复起来应该不难;
2011年6月,忙碌,顾不得恢复博客,博客无法访问;
2011年7月,兼职,依然没心思恢复,继续无法访问;
2011年8月,懒惰,更懒得理博客,还是无法访问;
2011年9月,借口,不想恢复,博客访问不了;
2011年10月,NND,还有什么借口和推辞,实在说不下去忍不下去看不过去了,就向国庆兄拿到了当初备份的文件,是一份采用gzip压缩过的压缩包文件alldata.sql.gz,使用gunzip alldata.sql.gz 解压缩该备份文件,并尝试单独恢复数据库;
然后,分享这次恢复过程中遇到的问题及解决方法:
1备份文件过大,包含当时所有后台其它数据库,gunzip解压之后的alldata.sql SQL文本文件信息如下:
[root@oracle11g ~]# ll -h
total 1.2G
drwxr-xr-x 4 root root 4.0K Aug 18 09:42 10gRAC_Media
drwxr-xr-x 7 root root 4.0K Sep 30 15:57 11gRAC_Media
-rw-r–r– 1 root root 1.2G Oct 18 13:38 alldata.sql
-rw——- 1 root root 1.4K Jan 27 2011 anaconda-ks.cfg
drwxr-xr-x 3 root root 4.0K Jan 29 2011 asm
drwxr-xr-x 2 root [...]
