Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1100307
  • 博文数量: 276
  • 博客积分: 10077
  • 博客等级: 上将
  • 技术积分: 2513
  • 用 户 组: 普通用户
  • 注册时间: 2007-08-24 20:31
文章分类

全部博文(276)

文章存档

2020年(1)

2015年(5)

2012年(2)

2011年(6)

2010年(7)

2009年(224)

2008年(31)

我的朋友

分类: Oracle

2009-02-03 08:58:05

我们来列举一个最简单的hash算法。假设我们的数值列表最多可以有10个元素,也就是有10个hash buckets,每个元素最多可以包含20个数值。则对应的二维数组就是t[10][20].我们可以定义hash算法为n MOD 10.通过这种算法,可以将所有进入的数据均匀放在10个hash bucket里面,hash bucket编号从0到9.比如,我们把1到100都通过这个hash函数均匀放到这10个hash bucket里,当查找32在哪里时,只要将32 MOD 10等于2,这样就知道可以到2号hash bucket里去找,也就是到t[2][20]里去找,2号hash bucket里有10个数值,逐个比较2号hash bucket里是否存在32就可以了。

  library cache就是使用多个hash bucket来管理的,其hash算法当然比我们前面列举的要复杂多了。每个hash bucket后面都串连着多个句柄(该句柄叫做library cache object handle),这些句柄描述了library cache里的对象的一些属性,包括名称、标记、指向对象所处的内存地址的指针等。可以用下图一来描述library cache的整体结构。

图三

  当一条SQL语句进入library cache的时候,先将SQL文本转化为对应ASCII数值,然后对该这些ASCII数值进行hash函数的运算,传入函数的是SQL语句的名称(name,对于SQL语句来说其name就是SQL语句的文本)以及命名空间(namespace,对于SQL语句来说是“SQL AREA”,表示共享游标。可以从视图v$librarycache里找到所有的namespace)。运用hash函数后得到一个值,该值就是hash bucket的号码,从而该SQL语句被分配到该号的hash bucket里去。实际上,hash bucket就是通过串连起来的对象句柄才体现出来的,它本身是一个逻辑上的概念,是一个逻辑组,而不像对象是一个具体的实体。oracle根据 shared_pool_size所指定的shared pool尺寸自动计算hash buckets的个数,shared pool越大,则可以挂载的对象句柄就越多。

  当某个进程需要处理某个对象时,比如处理一条新进入的SQL语句时,它会对该SQL语句应用hash函数算法,以决定其所在的hash bucket的编号,然后进入该hash bucket进行扫描并比较。有可能会发生该对象的句柄存在,但是句柄所指向的对象已经被交换出内存的情况出现。这时对应的对象必须被再次装载(reload)。也可能该对象的句柄都不存在,这时进程必须重新构建一个对象句柄挂到hash bucket上,然后再重新装载对象。SQL语句相关的对象有很多(最直观的就是SQL语句的文本),这些对象都存放在library cache里,它们都通过句柄来访问。可以把library cache理解为一本书,而SQL语句的对象就是书中的页,而句柄就是目录,通过目录可以快速定位到指定内容的页。

  对象句柄存放了对象的名称(name)、对象所属的命名空间(namespace)、有关对象的一些标记(比如对象是否为只读、为本地对象还是远程对象、是否被pin在内存中等等)以及有关对象的一些统计信息等。而且,对象句柄中还存放了当前正在lock住和pin住该对象的用户列表、以及当前正在等待 lock和pin该对象的用户列表。对象句柄中存放的最重要的内容就是指向Heap 0对象的指针了。Heap 0用来存放与对象有直接关系的一些信息,比如对象类型、对象相关的表(比如依赖表、子表等)、指向对象的其他数据块的指针(这些数据块指向了实际存放 SQL文本、PL/SQL代码、错误信息等的大内存块,这些大内存块依次叫做Heap 1、2、3、4等)等信息。

Heap是通过调用进程进行分配的,任何对象都具有heap 0,至于还应该分配哪些其他的heap则是由对象的类型决定的,比如SQL游标具有heap 1和 6,而PL/SQL程序包则具有heap 1、2、3和4.按照heap的使用情况,oracle会在SGA(library cache)、PGA或UGA中分配heap,但是heap 0始终都是在library cache中进行分配的。如果所请求的heap已经在SGA中分配了,则不会在PGA中再次分配heap.Heap是由一个或多个chunk组成的,这些 chunk可以是分散的分布在library cache中的,不需要连续分布。

  如上图三中所看到的heap 0实际上是指heap 0的句柄,其中包含的对象包括:

  1) object type:library cache中的对象类型包括:表、视图、索引、同名词等等。每个对象只能有一个object type,根据object type将对象归类到不同的namespace里。一个object type对应一个namespace,但是一个namespace可能对应多个object type.这样的话,查找一个对象时,只要在该对象所属的namespace中去找就可以了。比较常见的namespace包括:

  a) SQL AREA:也可以叫做CRSR,表示shared cursor,存放共享的SQL语句。

  b) TABLE/PROCEDURE:存放的object type包括:table、view、sequence、synonym、 procedure的定义、function的定义以及package的定义。

  c) BODY:存放procedure的实际代码、function的实际代码以及package的实际代码。

  d) TRIGGER:存放的object type为trigger.

  e) INDEX:存放的object type为index.

  2) object name:对象名称由三部分组成:

  a) Schema的名称,对于共享游标(SQL语句或PL/SQL程序块)来说为空。

  b) 对象名称。分为两种情况:对于共享游标(SQL语句或PL/SQL程序块)来说,其对象名称就是SQL的语句本身;而对于其他对象(比如表、视图、索引等)就是其在数据字典中的名称。

  c) Database link的名称。这是可选的,如果是本地对象,则为空。

  这样,对象的名称的格式为:.比如,可以为,也可以为hr.employees等。

  3) flags:flags主要用来描述对象是否已经被锁定。对象具有三种类型的flag:

  a) public flag:表示对象上没有锁定(pin)或者latch.

  b) status flag:表示对象上存在锁定(pin),说明对象正在被创建或删除或修改等。

  c) specitial flag:表示对象上存在library cache latch.

  4) tables:对每个对象,都会维护以下一串tables中的若干个:

  a) dependency table:含有当前对象所依赖的其他对象。比如一个视图可能会依赖其组成的多个表、一个存储过程可能依赖其中所调用的其他存储过程、一个游标可能依赖其中所涉及到的多个表等。Dependency table中的每个条目都指向一块物理内存,该物理内存中含有当前对象所依赖的对象的句柄。

  b) child table:含有当前对象的子对象,只有游标具有child table.Child table中的每个条目都指向一个可执行的SQL命令所对应的句柄。

  c) translation table:包含当前对象所引用的名称是如何解释为oracle底层对象的名称,只有游标具有translation table.

  d) authorization table:包含该对象上所对应的权限,一个条目对应一个权限。

  e) access table:对于dependency table中的每一个条目,都会在access table中存在对应的一个或多个条目。比如,假设对象A依赖对象B,那么在A的dependency table和access table中都会存在一个条目指向B.位于access table中的指向B的条目说明了对B具有什么样的访问类型,从而也就说明了用户要执行A则必须具有对B的权限。

  f) read-only dependency table:类似于dependency table,但是存放只读的对象。

  g) schema name table:包含authorization table中的条目所属的schema.

5) data blocks:对象的其他信息会存放在不同的heap中,为了找到这些heap,会在heap 0中存放多个(最多16个,但是这16个data block不会都用到)data blocks结构,每个data block含有指向这些实际heap内存块的指针。

  除了heap 0以外,还有11个heap,根据对象的不同进行分配,并存放了不同的内容:

  1) Heap 1:存放PL/SQL对象的源代码。

  2) Heap 2:存放PL/SQL对象的解析树,这有个好听的名字: DIANA.

  3) Heap 3:存放PL/SQL对象的伪代码。

  4) Heap 4:存放PL/SQL对象的基于硬件的伪代码。

  5) Heap 5:存放了编译时的错误信息。

  6) Heap 6:存放了共享游标对象的SQL文本。

  7) Heap 7:可用空间。

  8) Heaps 8–11:根据对象的不同而使用的子heap.

  我们可以通过查询v$db_object_cache来显示library cache中有哪些对象被缓存,以及这些对象的大小

  尺寸。比如,我们可以用下面的SQL语句来显示每个namespace中,大小尺寸排在前3名的对象:

  select *

  from (select row_number() over(partition by namespace order by sharable_mem desc) size_rank,

  namespace,

  sharable_mem,

  substr(name, 1, 50) name

  from v$db_object_cache

  order by sharable_mem desc)

  where size_rank <= 3

  order by namespace, size_rank;

阅读(1125) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~