約束、視圖、序列、僞列和索引

版權聲明:本文爲[博主](https://zhangkn.github.io)原創文章。未經博主贊成不得轉載。https://creativecommons.org/licenses/by-nc-sa/2.5/cn/ https://blog.csdn.net/u011018979/article/details/25560087

前言

約束條件用於保證數據的完整性。主要有主鍵約束(primary key)/非空約束(not null)、惟一約束(unique) 檢查約束(check)和外鍵約束(foreign key).css

正文

約束

主鍵約束(primary key)

主鍵約束包括了非空和惟一html

create table 表名(字段名 字段類型(長度) 約束條件);java

1.建立本身定義名稱約束git

create table 表名(字段名 字段類型(長度),constraint 約束名 約束類型(字段名));github

注:可以經過user_constraints數據字典來查詢約束。sql

 

非空約束(not null)

 檢查約束(check)

create table t_test(id number(10);sex char(2); constraint test_sex check (sex in('男'。‘女’)));--可以經過在字段後面加 default 值。來設置默認值;在使用默認值時使用defaultkeyword。數據庫

注:元組上的約束的定義oracle

元組級別的限制可以設置不一樣屬性之間取值的相互約束條件函數

check(ssex='女' or sname NOT like 'MS.%');--當學生性別爲男時。其名字不能以MS.開頭。post

 

外鍵約束(foreign key 字段名 references 表名(字段名)).

外鍵字段可以爲空,或者引用自依賴的父項。

設置級聯

1.賦予空值

foreign key(外鍵字段) references 表名(字段) on delete set null;

2.級聯刪除

foreign key(外鍵字段) references 表名(字段) on delete cascade;

聯合主鍵

constraint pk_t_emp primary key (字段1,字段2);

DDL操做約束

alter table 表名 drop contraints 約束名稱。

alter table 表名 add  contraints 約束名稱 約束類型(字段);

alter table 表名 modify (字段 字段類型 要加入的約束);

視圖

1.create or replace view 視圖名 as select  * from emp;

2.視圖是一種虛擬的表,具備和物理表一樣的功能,可以對視圖進行增、改和查詢。

視圖通常是一個表或多個表的行或列的子集。

3.對視圖的改動不影響基本表。

4.視圖使咱們得到數據更easy。

注:

複雜視圖的定義是。視圖中的數據不能直接經過表得到,必須經過計算來得到;複雜視圖的查詢字段必須取別名。

序列

序列是數據庫中特有的一組可以實現本身主動增加的數字。

create sequence 序列名 increment by  每次增加的步長 start with 起始值。

1.select 序列名.nextval from dual.--獲取序列的下一個值;獲取序列的當前值採用currval屬性。

僞列

oracle特有的默認提供給每一個表的。以便實現某些功能。

rownum

表示每條記錄的序號(查到結果集後才分配的序號),常常常使用於分頁。

 

rowid

表示每條記錄的惟一標識(一組32爲的字符串),可用來獲取記錄的物理地址

樣例1:刪除表中的一樣記錄

方法一:

delete from  t_table t1 where t1.rowid!=(select max(rowid) from t_table t2 where t1.id=t2.id and t.name=t2.name);;--當中 t1.id=t2.id and t.name=t2.name是定義一樣記錄的條件

方法二:

delete from t_table where roeid not in(select  max(rowid) from t_table group by 字段一,字段二);

樣例1:刪除表中不反覆的記錄

delete from  t_table t1 where t1.rowid=(select max(rowid) from t_table t2 where t1.id=t2.id and t.name=t2.name) and t1.rowid=(select min(rowid) from t_table t2 where t1.id=t2.id and t.name=t2.name) ;

應用於分頁

1.三目運算來計算總頁數 totalpage=sum/pagesize+sum%pagesize==0?0:1;//計算總頁數,sum爲總記錄數

2.第page頁的記錄的起始位置和結束位置分別爲:

pagesize*(page-1)+1。起始位置

pagesize*page;j、結束位置

注:

1.可以使用差集(minus)在數據庫查詢中實現分頁,但效率低'

2.常用子查詢將rownum做爲還有一結果集的字段來實現分頁。

select ee.* from(select e.* , rownum rr from (select * from emp where sal is not  null order by sal ) e )ee where ee.rr berween &start and &end。

3.rownum的分頁地java代碼演示樣例

package com.zhongxin.backstage.biz.impl; import java.util.List; import com.zhongxin.backstage.bean.CardPage; import com.zhongxin.backstage.bean.PlatePage; import com.zhongxin.backstage.biz.CardContextBiz; import com.zhongxin.backstage.dao.CardContextDao; import com.zhongxin.backstage.dao.PlateContextDao; import com.zhongxin.exception.DAOException; import com.zhongxin.entity.MainCard; import com.zhongxin.entity.Plate; import com.zhongxin.factory.Factory; import com.zhongxin.util.DeleteSpaceUtil; public class CardContextBizImpl implements CardContextBiz { private int pageSize=10; private CardContextDao dao=(CardContextDao) Factory.getImpl("CardContextDaoImpl");//定義dao層 public CardPage searchAllCard(int pageNum) throws DAOException { // 獲取所有的帖子 //計算分頁的頁面總數 CardPage cardPage=(CardPage) Factory.getImpl("CardPage"); String sql="select count(*) from tb_mainCard "; int totalCount=dao.getTotalCount(sql); int totalPage=(totalCount/this.getPageSize())+(totalCount%this.getPageSize()==0?0:1); //處理請求頁面大於總頁面的狀況 if(pageNum>totalPage){ pageNum=totalPage; } if(pageNum<=0){ pageNum=1; } cardPage.setTotalPage(totalPage); cardPage.setCurrPage(pageNum); if(totalCount==0){ return cardPage; } //使用基於查詢的分頁 int start=(pageNum-1)*this.getPageSize()+1; int end=pageNum*this.getPageSize(); //調用dao層的方法獲取顯示數據 List list=dao.searchCardByPage(start,end); cardPage.setCard(list); return cardPage; } public int getPageSize() { return pageSize; } public void setPageSize(int pageSize) { this.pageSize = pageSize; } public CardContextDao getDao() { return dao; } public void setDao(CardContextDao dao) { this.dao = dao; } public CardPage searchCardById(int pageNum,long id) throws DAOException { //依據id獲取主貼信息 //計算分頁的頁面總數 CardPage cardPage=(CardPage) Factory.getImpl("CardPage"); String sql="select count(*) from tb_mainCard where cardId="+id; int totalCount=dao.getTotalCount(sql); int totalPage=(totalCount/this.getPageSize())+(totalCount%this.getPageSize()==0?0:1); //處理請求頁面大於總頁面的狀況 if(pageNum>totalPage){ pageNum=totalPage; } if(pageNum<=0){ pageNum=1; } cardPage.setTotalPage(totalPage); cardPage.setCurrPage(pageNum); if(totalCount==0){ return cardPage; } //使用基於查詢的分頁 int start=(pageNum-1)*this.getPageSize()+1; int end=pageNum*this.getPageSize(); //調用dao層的方法獲取顯示數據 List list=dao.searchCardByPage(start,end,id); cardPage.setCard(list); return cardPage; } public CardPage searchAllCardBySendPeople(int pageNum, String name) throws DAOException { //依據發帖人獲取主貼細信息 //計算分頁的頁面總數 CardPage cardPage=(CardPage) Factory.getImpl("CardPage"); String sql="select count(*) from tb_mainCard where name='"+name+"'"; int totalCount=dao.getTotalCount(sql); int totalPage=(totalCount/this.getPageSize())+(totalCount%this.getPageSize()==0?0:1); //處理請求頁面大於總頁面的狀況 if(pageNum>totalPage){ pageNum=totalPage; } if(pageNum<=0){ pageNum=1; } cardPage.setTotalPage(totalPage); cardPage.setCurrPage(pageNum); if(totalCount==0){ return cardPage; } //使用基於查詢的分頁 int start=(pageNum-1)*this.getPageSize()+1; int end=pageNum*this.getPageSize(); //調用dao層的方法獲取顯示數據 List list=dao.getCardByPageAndPeopleName(start,end,name); cardPage.setCard(list); return cardPage; } public CardPage searchAllCardByTime(int pageNum, String time) throws DAOException { // 依據時間獲取主貼 //計算分頁的頁面總數 if(time.contains(".")){ time=time.substring(0,time.lastIndexOf("."));//去掉時間的秒的小數點 } CardPage cardPage=(CardPage) Factory.getImpl("CardPage"); String sql="select count(*) from tb_mainCard where time=to_date('"+time+"','yyyy-mm-dd hh24:mi:ss')"; //System.out.println(sql); int totalCount=dao.getTotalCount(sql); int totalPage=(totalCount/this.getPageSize())+(totalCount%this.getPageSize()==0?0:1); //處理請求頁面大於總頁面的狀況 if(pageNum>totalPage){ pageNum=totalPage; } if(pageNum<=0){ pageNum=1; } cardPage.setTotalPage(totalPage); cardPage.setCurrPage(pageNum); if(totalCount==0){ return cardPage; } //使用基於查詢的分頁 int start=(pageNum-1)*this.getPageSize()+1; int end=pageNum*this.getPageSize(); //調用dao層的方法獲取顯示數據 String sql2="select * from (select rownum r,t.* from ("+"select * from tb_mainCard where time=to_date('"+time+"','yyyy-mm-dd hh24:mi:ss')"+") t) t1" + " where t1.r between "+start+" and "+end; List list=dao.getCard(sql2); cardPage.setCard(list); return cardPage; } //SQL> select * from emp where hiredate between (to_date('1981-2-20','yyyy-mm-dd')) and (to_date('1981-2-23','yyyy-mm-dd')); public CardPage searchAllCardByTimeInnerOneDay(int pageNum, String time) throws DAOException { //依據某個時間點的一天內查詢的主貼 //計算分頁的頁面總數 if(time.contains(".")){ time=time.substring(0,time.lastIndexOf("."));//去掉時間的秒的小數點 } CardPage cardPage=(CardPage) Factory.getImpl("CardPage"); String sql="select count(*) from tb_mainCard where time between to_date('"+time+"','yyyy-mm-dd hh24:mi:ss')"+"and to_date('"+time+"','yyyy-mm-dd hh24:mi:ss')+1"; //System.out.println(sql); int totalCount=dao.getTotalCount(sql); int totalPage=(totalCount/this.getPageSize())+(totalCount%this.getPageSize()==0?

0:1); //處理請求頁面大於總頁面的狀況 if(pageNum>totalPage){ pageNum=totalPage; } if(pageNum<=0){ pageNum=1; } cardPage.setTotalPage(totalPage); cardPage.setCurrPage(pageNum); if(totalCount==0){ return cardPage; } //使用基於查詢的分頁 int start=(pageNum-1)*this.getPageSize()+1; int end=pageNum*this.getPageSize(); //調用dao層的方法獲取顯示數據 String sql2="select * from (select rownum r,t.* from ("+"select * from tb_mainCard where time between to_date('"+time+"','yyyy-mm-dd hh24:mi:ss')"+"and to_date('"+time+"','yyyy-mm-dd hh24:mi:ss')+1"+") t) t1" + " where t1.r between "+start+" and "+end; List list=dao.getCard(sql2); cardPage.setCard(list); return cardPage; } public CardPage searchAllCardByOrderTime(int pageNum, String time) throws DAOException { // 依據查詢某個時間點至今的有主貼,並按時間排序 //計算分頁的頁面總數 if(time.contains(".")){ time=time.substring(0,time.lastIndexOf("."));//去掉時間的秒的小數點 } CardPage cardPage=(CardPage) Factory.getImpl("CardPage"); String sql="select count(*) from tb_mainCard where time between to_date('"+time+"','yyyy-mm-dd hh24:mi:ss')"+"and sysdate"; //System.out.println(sql); int totalCount=dao.getTotalCount(sql); int totalPage=(totalCount/this.getPageSize())+(totalCount%this.getPageSize()==0?0:1); //處理請求頁面大於總頁面的狀況 if(pageNum>totalPage){ pageNum=totalPage; } if(pageNum<=0){ pageNum=1; } cardPage.setTotalPage(totalPage); cardPage.setCurrPage(pageNum); if(totalCount==0){ return cardPage; } //使用基於查詢的分頁 int start=(pageNum-1)*this.getPageSize()+1; int end=pageNum*this.getPageSize(); //調用dao層的方法獲取顯示數據 String sql2="select * from (select rownum r,t.* from ("+"select * from tb_mainCard where time between to_date('"+time+"','yyyy-mm-dd hh24:mi:ss')"+"and sysdate"+") t) t1" + " where t1.r between "+start+" and "+end+" order by time "; List list=dao.getCard(sql2); cardPage.setCard(list); return cardPage; } public CardPage searchAllCardBySubject(int pageNum, String subject) throws DAOException { //依據主題獲取主貼信息 CardPage cardPage=(CardPage) Factory.getImpl("CardPage"); String sql="select count(*) from tb_mainCard where subject='"+subject+"'"; //System.out.println(sql); int totalCount=dao.getTotalCount(sql); int totalPage=(totalCount/this.getPageSize())+(totalCount%this.getPageSize()==0?0:1); //處理請求頁面大於總頁面的狀況 if(pageNum>totalPage){ pageNum=totalPage; } if(pageNum<=0){ pageNum=1; } cardPage.setTotalPage(totalPage); cardPage.setCurrPage(pageNum); if(totalCount==0){ return cardPage; } //使用基於查詢的分頁 int start=(pageNum-1)*this.getPageSize()+1; int end=pageNum*this.getPageSize(); //調用dao層的方法獲取顯示數據 String sql2="select * from (select rownum r,t.* from ("+"select * from tb_mainCard where subject='"+subject+"') t) t1" + " where t1.r between "+start+" and "+end+" order by subject "; List list=dao.getCard(sql2); cardPage.setCard(list); return cardPage; } public CardPage searchAllCardByLikeSubject(int pageNum, String subject) throws DAOException { //依據帖子的主題查詢主貼支持模糊查詢 subject=DeleteSpaceUtil.deleteSpace(subject);//除掉模糊查詢的keyword的中間空白 CardPage cardPage=(CardPage) Factory.getImpl("CardPage"); String sql="select count(*) from tb_mainCard where subject like '%"+subject+"%'"; //System.out.println(sql); int totalCount=dao.getTotalCount(sql); int totalPage=(totalCount/this.getPageSize())+(totalCount%this.getPageSize()==0?0:1); //處理請求頁面大於總頁面的狀況 if(pageNum>totalPage){ pageNum=totalPage; } if(pageNum<=0){ pageNum=1; } cardPage.setTotalPage(totalPage); cardPage.setCurrPage(pageNum); if(totalCount==0){ return cardPage; } //使用基於查詢的分頁 int start=(pageNum-1)*this.getPageSize()+1; int end=pageNum*this.getPageSize(); //調用dao層的方法獲取顯示數據 String sql2="select * from (select rownum r,t.* from ("+"select * from tb_mainCard where subject like '%"+subject+"%') t) t1" + " where t1.r between "+start+" and "+end+" order by time "; List list=dao.getCard(sql2); cardPage.setCard(list); return cardPage; } public CardPage searchAllCardByNum(int pageNum, int num) throws DAOException { //依據回帖數查詢主貼 CardPage cardPage=(CardPage) Factory.getImpl("CardPage"); String sql="select count(*) from tb_mainCard where replyNum="+num; //System.out.println(sql); int totalCount=dao.getTotalCount(sql); int totalPage=(totalCount/this.getPageSize())+(totalCount%this.getPageSize()==0?0:1); //處理請求頁面大於總頁面的狀況 if(pageNum>totalPage){ pageNum=totalPage; } if(pageNum<=0){ pageNum=1; } cardPage.setTotalPage(totalPage); cardPage.setCurrPage(pageNum); if(totalCount==0){ return cardPage; } //使用基於查詢的分頁 int start=(pageNum-1)*this.getPageSize()+1; int end=pageNum*this.getPageSize(); //調用dao層的方法獲取顯示數據 String sql2="select * from (select rownum r,t.* from ("+"select * from tb_mainCard where replyNum="+num+") t) t1" + " where t1.r between "+start+" and "+end+" order by replyNum "; List list=dao.getCard(sql2); cardPage.setCard(list); return cardPage; } public CardPage searchAllCardByGreateNum(int pageNum, int num) throws DAOException { // if(num<0){ num=0; } CardPage cardPage=(CardPage) Factory.getImpl("CardPage"); String sql="select count(*) from tb_mainCard where replyNum>="+num; //System.out.println(sql); int totalCount=dao.getTotalCount(sql); int totalPage=(totalCount/this.getPageSize())+(totalCount%this.getPageSize()==0?0:1); //處理請求頁面大於總頁面的狀況 if(pageNum>totalPage){ pageNum=totalPage; } if(pageNum<=0){ pageNum=1; } cardPage.setTotalPage(totalPage); cardPage.setCurrPage(pageNum); if(totalCount==0){ return cardPage; } //使用基於查詢的分頁 int start=(pageNum-1)*this.getPageSize()+1; int end=pageNum*this.getPageSize(); //調用dao層的方法獲取顯示數據 String sql2="select * from (select rownum r,t.* from ("+"select * from tb_mainCard where replyNum>="+num+") t) t1" + " where t1.r between "+start+" and "+end+" order by replyNum "; List list=dao.getCard(sql2); cardPage.setCard(list); return cardPage; } public CardPage searchAllCardByPerfectCard(int pageNum, String perfectCard) throws DAOException { // 查看精品帖 //進行頁面顯示的內容與數據庫的表示轉化 int num=0; if("yes".equals(perfectCard)){ String sql="select count(*) from tb_mainCard where perfectCard!="+num; System.out.println(sql); CardPage cardPage=(CardPage) Factory.getImpl("CardPage"); //System.out.println(sql); int totalCount=dao.getTotalCount(sql); int totalPage=(totalCount/this.getPageSize())+(totalCount%this.getPageSize()==0?0:1); //處理請求頁面大於總頁面的狀況 if(pageNum>totalPage){ pageNum=totalPage; } if(pageNum<=0){ pageNum=1; } cardPage.setTotalPage(totalPage); cardPage.setCurrPage(pageNum); if(totalCount==0){ return cardPage; } //使用基於查詢的分頁 int start=(pageNum-1)*this.getPageSize()+1; int end=pageNum*this.getPageSize(); //調用dao層的方法獲取顯示數據 String sql2="select * from (select rownum r,t.* from ("+"select * from tb_mainCard where perfectCard!="+num+") t) t1" + " where t1.r between "+start+" and "+end+""; List list=dao.getCard(sql2); cardPage.setCard(list); return cardPage; }else{ String sql="select count(*) from tb_mainCard where perfectCard="+num; CardPage cardPage=(CardPage) Factory.getImpl("CardPage"); //System.out.println(sql); int totalCount=dao.getTotalCount(sql); int totalPage=(totalCount/this.getPageSize())+(totalCount%this.getPageSize()==0?0:1); //處理請求頁面大於總頁面的狀況 if(pageNum>totalPage){ pageNum=totalPage; } if(pageNum<=0){ pageNum=1; } cardPage.setTotalPage(totalPage); cardPage.setCurrPage(pageNum); if(totalCount==0){ return cardPage; } //使用基於查詢的分頁 int start=(pageNum-1)*this.getPageSize()+1; int end=pageNum*this.getPageSize(); //調用dao層的方法獲取顯示數據 String sql2="select * from (select rownum r,t.* from ("+"select * from tb_mainCard where perfectCard="+num+") t) t1" + " where t1.r between "+start+" and "+end+""; List list=dao.getCard(sql2); cardPage.setCard(list); return cardPage; } } public CardPage searchAllCardByPlateName(int pageNum, String plateName) throws DAOException { //依據板塊獲取主貼 CardPage cardPage=(CardPage) Factory.getImpl("CardPage"); String sql="select count(*) from tb_mainCard where plateName='"+plateName+"'"; //System.out.println(sql); int totalCount=dao.getTotalCount(sql); int totalPage=(totalCount/this.getPageSize())+(totalCount%this.getPageSize()==0?0:1); //處理請求頁面大於總頁面的狀況 if(pageNum>totalPage){ pageNum=totalPage; } if(pageNum<=0){ pageNum=1; } cardPage.setTotalPage(totalPage); cardPage.setCurrPage(pageNum); if(totalCount==0){ return cardPage; } //使用基於查詢的分頁 int start=(pageNum-1)*this.getPageSize()+1; int end=pageNum*this.getPageSize(); //調用dao層的方法獲取顯示數據 String sql2="select * from (select rownum r,t.* from ("+"select * from tb_mainCard where plateName='"+plateName+"') t) t1" + " where t1.r between "+start+" and "+end+" order by replyNum "; List list=dao.getCard(sql2); cardPage.setCard(list); return cardPage; } public boolean deleteCardById(long id) throws DAOException { //刪除主貼 int num =dao.deleteCardById(id); //System.out.println(num); if(num==1){ return true; }else{ return false; } } public boolean deleteCardById(String[] arrId) throws DAOException { //刪除選中的主貼 return dao.deleteCardByArrId(arrId); } }

 

索引

高速的查找定位到某條記錄(底層採用rowid來實現);沒有索引查找時,將採用全表掃描(full table scan)

注:

1.查找索引可以使用user_indexes數據字典。

2數據庫.默以爲表中的主鍵和惟一鍵創建索引。

本身定義索引

create index 索引名 on 表名(字段名)。

不該該應用索引的狀況

1.常常進行更新操做的字段

2.表小,查詢結果集大

3.不常用的字段

應用索引的狀況

1.經常用來查詢的字段

2.當表的數據量很是大且查詢的結果集較小

3.當前字段值很是多爲空的字段

4.經常用來做爲聯合查詢的字段

5.外鍵字段

注:說說你對索引的認識(索引的結構、對dml的影響、對查詢的影響和爲何提升查詢性能)?

1。

索引有b-tree和cluster等類型。oracle使用了一個複雜的自平衡b-tree結構。

2.一般來講在表上創建適當的索引,在查詢時會改進查詢性能。

3.但在進行插入、改動和刪除是。同一時候會進行索引的改動,在性能上有必定的影響。索引一般可以提升select、update和delete的性能。但會下降insert的速度。

4,。有索引且在查詢條件使用索引時,數據庫會先讀取索引,再依據索引內容和查詢條件來查詢出rowid,最後依據rowid取出需要的數據。

由於索引內容一般比全表內容要少很是多,所以經過先讀索引可以下降I/O,提升查詢性能。

 

對索引操做的法則

1.避免對索引字段進行計算操做

2.避免在索引字段上使用not、<、>、和!=

3.避免在索引列上使用is null 和 is not null。

4.避免在索引列上出現數據類型轉換

5.避免在索引字段上使用函數

6.避免在創建索引的列中使用空值.

 

數據字典

存儲描寫敘述對象(表。序列、視圖、觸發器、過程、函數等)信息的表或視圖稱爲數據字典。

user_XXX 表示當前用戶的相關信息的數據字典

user_tables/user_constraints/user_indexes/user_sequences/user_views/user_objects

好比:select distinct object——type from user_objects;--查看所有的對象

user_all_XXX 當前用戶所能訪問的對象的數據字典

dba_xxx  當前數據庫下得所有對象的數據字典

 

總結

table space

一個數據庫劃分爲一個或多個邏輯單元,該邏輯單元稱爲表空間。block(塊)組成extent(長度),extent組成segment(段)。segment組成tablespace。

block

1.block是Oracle中存儲數據塊的最小單位,因此數據終於都是存儲在block中。它也被稱爲邏輯blocks或是頁(pages)。

2.每一個操做系統都有本身的block size。

而這裏的block是Oracle本身的,不一樣於OS的blocks。可以經過設置DB_BLOCK_SIZE設置Oracle的block爲OS的block的幾倍。從而下降沒必要要的I/O。不管block中存放的數據是表、索引仍是cluster data,block的結構都是一致:

3.  @ block header: 這裏主要存儲一些數據塊的基本信息,如數據塊地址,塊類型(table data, index等),以及一些事務信息。

爲了增強理解,咱們dump一下block看看:
SQL> select dbms_rowid.rowid_relative_fno(rowid) as fno, dbms_rowid.rowid_block_number(rowid) from t1 where b=1;
       FNO DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
———- ————————————
         4                                  388
SQL> alter system dump datafile 4 block 388;
在dump file中,咱們看到
Block header dump:  0×01000184
Object id on Block? Y
seg/obj: 0xcd17  csc: 0×00.8d80b  itc: 2  flg: E  typ: 1 – DATA
     brn: 0  bdba: 0×1000181 ver: 0×01 opc: 0
     inc: 0  exflg: 0
# 下面是一些比較重要的事務信息。每當一個事務開始時,都要得到一個ITL entry, 不然將會出現ITL 等待。
Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0×01   0×0002.005.0000010b  0×00800024.0128.32  –U-   66  fsc 0×0000.0008d8f3
0×02   0×0000.000.00000000  0×00000000.0000.00  —-    0  fsc 0×0000.00000000
data_block_dump,data header at 0xceb6864


4.  @ table directory 記錄該塊中 table rows 的信息,例如如下所看到的:
===============
tsiz: 0×1f98
hsiz: 0×96
pbl: 0×0ceb6864
bdba: 0×01000184
     76543210
flag=——–
ntab=1  // no. of tables, 除了cluster 之外。普通狀況都爲一
nrow=66 // 該block 上 rows 的數目
frre=-1
fsbo=0×96
fseo=0×402
avsp=0×36c
tosp=0×36c
 5.@ row directroy 記錄該塊中記錄的每一條記錄的地址信息。例如如下所看到的:
0×12:pri[0]     offs=0×402
0×14:pri[1]     offs=0×46d
0×16:pri[2]     offs=0×4d8


0×92:pri[64]    offs=0×1ec2
0×94:pri[65]    offs=0×1f2d
        終於的記錄條數應該和table directory 中的nrows相等。

這部分空間一旦被分配,將不可能收回,僅僅能在有新行insert時被重用。


**  overhead:在block中,上述的header、table directory和row directory被合稱爲overhead。


6.  @ row data 記錄表中的實際數據。
7.  @ free space 該部分主要用於update,insert等操做。 同一時候ITL entry 也可以在該部分得到。


附註: 在data block中的free space的使用與優化

1.當數據被delete或update時,可能引發block產生free space對此:

①假設有insert語句與對應釋放block space的語句在同一個transaction中,則insert可以使用剛剛釋放的block space。

②假設insert語句與對應的釋放block space的語句不在同一個transaction中。則釋放的block space僅僅有在事務被commit以後才幹被使用。

Oracle當發生下面兩種狀況會進行free space的合併:insert或update操做視圖使用一個有足夠free space的block;free space存在大量碎片,沒法進行數據的insert等。

2. row的連接與遷移:

當一條記錄row的數據太大時。可能沒法放在一個block中,這樣的狀況下Oracle每每會使用chain(連接)的方法;此外。當one row被update後,數據量增大。當前的block已經不能全然容納時,Oracle會把該row數據整個遷移(migrates)到其它的數據塊中。但在原來row的位置上保存一個指針。連接到新的地址上,大量的遷移、連接將會下降DB的I/O性能。


extent

 

extent 是每次分配給一個對象的邏輯最小單位,是由必定數量連續的block組成。一個或多個extent又組成了一個segment。


1.  @ Extent的分配:

對於本地管理表空間。DB會先肯定可以分配extent的候選datafile,隨後查詢該datafile的bitmap,肯定是否有所需大小的連續空暇blocks。直到找到知足的datafile。假設使用dictionary managed tablespace,則是去查詢數據字典。而不是datafile頭部的bitmap信息。

另外,由於某些緣由,假設想手工非配extent時。可以使用alter table table_name allocate extent。


2.  @ Extent的收回:

1)當一個extent被分配給了某個object。除非這個obj被drop,不然extent將不會被其它obj所使用。除非 trauncate … drop storage.或者alter table … dealocate unused.(以上兩種方法都不適用於index)。

另外。對於rollback segments。假設指定了optimal參數。oracle會本身dealocate一些extent。


2)   在dictionary managed tablespace中,假設所請求的ext 大於各個free extents 大小,這是oracle將聚合臨近的extent。造成一個更大的extent。

在local managed tablespace中。則無此限制。 一旦extent 被分配和回收,對應的文件頭bitmap或者數據字典都會被更新。

 

segment

 

它是extents的集合,它包括了在表空間中所包括的詳細邏輯存儲機構的所有extents。

好比一個未分區的table,index, cluster被成爲一個段,一個被分區的index,table的一個partition 被成爲一個段。對於temporary segment。主要用於排序等操做。僅僅有當DB的內存沒法存放對應的排序操做並沒有法找到其它更好的解決的方法時。纔會在暫時表空間中建立temporary segment。

1.下面語句均可能要建立temporary segment。 CREATE INDEX SELECT ... ORDER BY SELECT DISTINCT ... SELECT ... GROUP BY SELECT . . . UNION SELECT ... INTERSECT SELECT ... MINUS

相關文章
相關標籤/搜索