暨上通过预编译阐述道共享池最后到SGA,这里进一步说明一下SGA中另一个大块,数据缓冲区,携带提及一点数据文件和表空间,后续专门会说明这块。
首先了解下SGA种大致有那些东西,这些东西随着数据库版本的增加会有所增加,不过大致上应该一致,这也是基本所有的体系结构都会描述的东西:
在认识数据缓冲区前,先记住几个常用的视图:
X$BH、GV$BH、V$BH、V$FIXED_TABLE、V$FIXED_VIEW_DEFINITION、DICT、DICT_COLUMNS。
以及两个包:DBMS_SPACE 和 DBMS_ROWID的一些常用内容,在后面会逐渐用到时说明部分使用方式,不过还是先要创建一个表,不然什么测试工作也做不了:
在一个用户下创建一个表:
CREATE TABLE TEST_OBJECTS
AS SELECT * FROM USER_OBJECTS;
如果那个用户下没有什么对象,那就多复制几次数据,才能填充一些数据,数据成倍增长:
INSERT INTO TEST_OBJECTS
SELECT * FROM TEST_OBJECTS;
COMMIT;
此时第一个,常规使用下,一个常用的对象就是ROWID,那么看下它由哪几部分组成:
对象编号、文件编号、文件内块号、块内部行号码,我们看下一张表内部每条数据的这些信息:
SQL>SELECT dbms_rowid.rowid_relative_fno(ROWID) "文件编号",
dbms_rowid.rowid_object(ROWID) "对象编号",
dbms_rowid.rowid_block_number(ROWID) "块编号",
dbms_rowid.rowid_row_number(ROWID) "块内部行号码"
FROM TEST_OBJECTS t;
文件编号 对象编号 块编号 块内部行号码
---------- ---------- ---------- ------------
4 54646 588 0
4 54646 588 1
4 54646 588 2
4 54646 588 3
4 54646 588 4
4 54646 588 5
4 54646 588 6
4 54646 588 7
4 54646 588 8
4 54646 588 9
4 54646 588 10
4 54646 588 11
4 54646 588 12
4 54646 588 13
4 54646 588 14
4 54646 588 15
4 54646 589 0
4 54646 589 1
4 54646 589 2
4 54646 589 3
其实对象编号是永远不会变化的,一般情况下也在同一个文件中,所以主要看的是BLOCK的信息。
付:文件号是对应数据文件的编号,对应视图DBA_DATA_FILES的FILE_ID字段。
对象编号是对象在整个数据库的唯一标识,对应DBA_OBJECTS的OBJECT_ID字段。
此时通过分析表:
BEGIN
dbms_stats.gather_table_stats('SCOTT','TEST_OBJECTS');
END;
后查询统计信息:
SELECT BLOCKS, NUM_ROWS
FROM USER_TABLES
WHERE TABLE_NAME = 'TEST_OBJECTS';
BLOCKS NUM_ROWS
---------- ----------
16 1024
再查询用户段信息:
SQL> SELECT t.segment_name,t.blocks FROM USER_SEGMENTS T
2 WHERE T.segment_name='TEST_OBJECTS';
SEGMENT_NAME BLOCKS
-------------------------------------------------------------------------------- ----------
TEST_OBJECTS 16
在查询根据上述统计出来的信息:
SQL> SELECT COUNT(DISTINCT dbms_rowid.rowid_block_number(ROWID))
2 FROM TEST_OBJECTS;
COUNT(DISTINCTDBMS_ROWID.ROWID
------------------------------
13
为什么不一样,因为内部有保留块,记录表头、位图信息,数据库始终比这个实际的段要小,通过测试可以发现,每次增长都会以8个块增长,但是数据实际的值,记录实际数据块大小,当发现两者之和大于实际大小,就需要扩展空间了。
上面有点开场白,这里再想下试验前需要明白,数据缓冲区用于在数据从磁盘中读取数据后到内存是以“块”为基本单位,不论块中存储多少行数据,分别有“单块读”和“多块读”两种方式,读入内存后,此时未了避免下次再重磁盘上去读取,减少磁盘读取开销,此时将这些块放入内存中,并采用LRU链表进行管理(ORACLE 8I后并非完全的LRU算法),当对这些数据修改时,内存采用一致性读块进行管理(一个块最多对应6个一致性读块),当数据缓冲区不够用的时候,就会将接使用较少的部分提取出来,将其替换到磁盘上去(其实就是在内存中将其指针删除),为简单证明这个情况,我们需要做一个简单试验,刚才创建的表,我们找几个块出来做实验(588块和589块吧,对象编号上述已经查询出来是:54646,文件号也能通过上述看出是:),我们首先通过X$BH视图查看其实用情况。
--X$BH需要在DBA用户下才可以使用,即使在全局数据字典:
V$FIXED_TABLE、V$FIXED_VIEW_DEFINITION、DICT
也找不到他的身影,因为它基本不被外界使用;
顺便说下全局视图:
V$FIXED_TABLE 查询所有的V$视图定义和X$视图信息,GV$视图普遍为集群类使用。
V$FIXED_VIEW_DEFINITION 查询所有V$视图、V$的定义部分
DICT 查询到所有字典的字典列表信息
三者很多信息都是重复的,关键字段有些变化。
通过V$FIXED_VIEW_DEFINITION视图可以找到X$BH定义了GV$BH,由GV$BH的大部分字段组成了V$BH。
另外如果要查询两个块下面的数据如何查询:
定位一下这两个快不是很好查,怎么查询呢,因为只是实验,也不用管太多,只要能得到要的结论即可,此时块信息是需要588~599两个块,那么我们怎么查询数据呢,通过ROWID,就需要DBMS_ROWID包来创建: ROWID >= DBMS_ROWID.ROWID_CREATE(1, 54646, 4, 588, 0)
AND ROWID < DBMS_ROWID.ROWID_CREATE(1, 54646, 4, 600, 0);
DBMS_ROWID.ROWID_CREATE用于创建ROWID,参数按顺序为:类型(直接写1即可),对象编号、文件编号、文件内块号、块内行号。
扯远了,回到话题,开始试验下:
而X$BH视图看下有那些字段(一看看花眼了,找到想要的就行了):
SQL> DESC X$BH
名称
-------------
ADDR
INDX
INST_ID
HLADDR
BLSIZ
NXT_HASH
PRV_HASH
NXT_REPL
PRV_REPL
FLAG
RFLAG
SFLAG
LRU_FLAG
TS#
FILE#
DBARFIL
DBABLK
CLASS
STATE
MODE_HELD
CHANGES
CSTATE
LE_ADDR
DIRTY_QUEUE
SET_DS
OBJ
BA
CR_SCN_BAS
CR_SCN_WRP
CR_XID_USN
CR_XID_SLT
CR_XID_SQN
CR_UBA_FIL
CR_UBA_BLK
CR_UBA_SEQ
CR_UBA_REC
CR_SFL
CR_CLS_BAS
CR_CLS_WRP
LRBA_SEQ
LRBA_BNO
HSCN_BAS
HSCN_WRP
HSUB_SCN
US_NXT
US_PRV
WA_NXT
WA_PRV
TCH
TIM
需要的字段有:文件号、对象编号、块号、TOUCH热度信息,分别对应字段:file#、obj、dbablk、tch信息,查看一下:
SQL> SELECT file#,dbablk,tch FROM x$bh
2 WHERE obj = 54646
3 AND dbablk in(588,589)
4 ORDER BY dbablk;
FILE# DBABLK TCH
---------- ---------- ----------
4 588 8
4 589 8
此时发现已经有一些操作,此时开始对第589块上任意一行数据查询(另起一个会话):
SELECT *
FROM TEST_OBJECTS T
WHERE ROWID = DBMS_ROWID.ROWID_CREATE(1, 54646, 4, 589, 0);
然后再执行上述SQL
SQL> /
FILE# DBABLK TCH
---------- ---------- ----------
4 588 8
4 589 9
有兴趣可以多做几次,每次都会有变化,注意,可能对同一个块查询出多条记录,那是一致性读的问题,很多涨块信息也在里面。
然后再执行一下清空数据缓冲区的操作,其实就是清空热点度的问题:
SQL> ALTER SYSTEM FLUSH BUFFER_CACHE;
系统已更改。
SQL> SELECT file#,dbablk,tch FROM x$bh
2 WHERE obj = 54646
3 AND dbablk in(588,589)
4 ORDER BY dbablk;
FILE# DBABLK TCH
---------- ---------- ----------
4 588 0
4 589 0
4 589 0
此时热点度的TCH都是0了,同样的方式可以去查询V$BH视图,V$BH中没有TCH这个字段,对应数据文件字段还是file#,而块字段是block#,提供一个状态字段status和flag字段来源其它视图,status指明被instance共享、专用、还是一致性读块、空闲块;flag按照和1、16、1536等等进行按位求与运算(通过函数bitand)得到块内部的信息,如是否为脏块、是否为临时块等等信息。
数据读取过程有两种方式:单块读(db file sequential)和多块读(db file scattered read),所谓单块读就是每次IO只读取一块到内存,主要看分布情况,一般我们用索引定位少量数据或者用ROWID定位少量数据时较多,但是也有其它情况,和多块读一起说明;多块读是一次读入多个连续块到内存中(一定是连续的),这个数据的上限是由参数db_file_multiblock_read_count参数指定,默认是16个块,可以根据实际情况作相应调整,不过很多时候它是一个理想数字,一般达不到,因为当数据缓冲区不够的时候会替换一些不常用的块到磁盘中,此时数据块在内存中的分布零散的,此时当在查询某个数据范围时,包含多个块,但是这些块在内存中非连续,那么就会按照断掉的部分到磁盘上去读取,此时就会选择单块读还是多块读了,此时较为消耗IO性能,最坏的情况是每个块断一块,所以在业务层面,对于多块信息在考虑查询过程中,保证和查询中的多块读的参数差不多是较为理想的选择(但是这个可能真的不好控制,不过应当有一定的理论计算值),否则在设计层面上,平均性能差距会产生几倍的差距。
另外对于常规小表并且经常查询的或者些经常查询的不太大的索引,此时我们习惯让他们放入内存中,此时使用对表的属性修改为内存表格即可:
ALTER TABLE <table_name> CACHE;
另外可以指定存放位置,默认情况下,ORACLE现在只会给与一个db_cache_size,它是常规的数据缓冲区信息,其实数据缓冲区还有两块分别为:db_keep_cache_size为几乎不会被替换出内存的区域,和db_recycle_cache_size几乎使用完就会被替换出内存的区域(付:如果为ORACLE 9i以前,不包括ORACLE 9i使用的参数为:db_block_buffer、db_pool_keep、db_pool_recycle)。
查询这几个参信息:
show parameter db_cache_size;
show parameter db_keep_cache_size;
show parameter db_recycle_cache_size;
或者通过视图:
SELECT * FROM v$buffer_pool_statistics;
若发现后两者没有数据则修改这记者的大小信息:
SQL>alter system set db_cache_size = 400M;
SQL>alter system set db_keep_cache_size = 150M;
SQL>alter system set db_recycle_cache_size = 50M;
这里需要注意的是:若要增加后面两者,需要先减少前者的大小,因为数据缓冲区毕竟还是一个整体,另外你设置的大小未必是实际的大小,ORACLE会根据你的设置做相应的细节调整,调整完成后,可以SHOW PARAMETER查看大小变化。
如上述表需要设置到KEEP区域进行存储,此时使用:
ALTER TABLE <table_name> STORAGE(BUFFER_POOL KEEP) cache;
同理其它区域分别设置:DEFAULT、RECYCLE,如果将一个已经是cache表修改为非cache表,此时将参数修改为nocache即可。
修改为cache表后,可以通过视图查看:
SELECT name,owner,type
FROM v$db_object_cache where kept = 'YES'
AND NAME ='表名称大写';
或者查询表的属性信息查看:
SELECT a.cache,a.BUFFER_POOL,a.table_name
FROM user_tables a
WHERE a.table_name = ‘表名称大写’;
从数据缓冲区可以看出内部运作和读取方式,根据实际情况中的一些便要设计中有一定用处,这也是一些基础,在后面文件管理(其实文件系统才是真正的数据库,现在说的都是实例内部的信息,他们是完全不同的概念),和索引原理上结合企业也许会更加清楚吧。
关于下一次应该是涉及物理结构的文件系统或者实例另一部分PGA相关说明。。。。