2008年12月3日 星期三



Creating Tablespace



CREATE TABLESPACE userdata
DATAFILE '/u01/oradata/userdata01.dbf' SIZE 100M
AUTOEXTEND ON NEXT 5M MAXSIZE 200M;





Creating User



CREATE USER tester
IDENTIFIED BY sysdba
DEFAULT TABLESPACE userdata
TEMPORARY TABLESPACE temp
QUOTA 15m ON userdata
PASSWORD EXPIRE;




Crant User



GRANT CREATE SESSION TO tester;

2008年10月29日 星期三

ORA-01102: cannot mount database in EXCLUSIVE mode

出處一:
http://www.dba-oracle.com/t_ora_01102_cannot_mount_database_in_exclusive_mode.htm

********************************

http://www.orafaq.com/forum/t/40030/0/

database is started in EXCLUSIVE mode by default. Therefore, the
ORA-01102 error is misleading and may have occurred due to one of the
following reasons:

- there is still an "sgadef.dbf" file in the "ORACLE_HOME/dbs"
directory
- the processes for Oracle (pmon, smon, lgwr and dbwr) still exist
- shared memory segments and semaphores still exist even though the
database has been shutdown
- there is a "ORACLE_HOME/dbs/lk" file

The "lk" and "sgadef.dbf" files are used for locking shared memory.
It seems that even though no memory is allocated, Oracle thinks memory is
still locked. By removing the "sgadef" and "lk" files you remove any knowledge
oracle has of shared memory that is in use. Now the database can start.

POSSIBLE SOLUTION:
Verify that the database was shutdown cleanly by doing the following:

1. Verify that there is not a "sgadef.dbf" file in the directory
"ORACLE_HOME/dbs".

% ls $ORACLE_HOME/dbs/sgadef.dbf

If this file does exist, remove it.

% rm $ORACLE_HOME/dbs/sgadef.dbf

2. Verify that there are no background processes owned by "oracle"

% ps -ef | grep ora_ | grep $ORACLE_SID

If background processes exist, remove them by using the Unix
command "kill". For example:

% kill -9

3. Verify that no shared memory segments and semaphores that are owned
by "oracle" still exist

% ipcs -b

If there are shared memory segments and semaphores owned by "oracle",
remove the shared memory segments

% ipcrm -m

and remove the semaphores

% ipcrm -s

NOTE: The example shown above assumes that you only have one
database on this machine. If you have more than one
database, you will need to shutdown all other databases
before proceeding with Step 4.

4. Verify that the "$ORACLE_HOME/dbs/lk" file does not exist

5. Startup the instance

//////////////////////////////////////

出處二
http://www.dbifan.com/?p=248

ORA-01102: cannot mount database in EXCLUSIVE mode

今天在STARTUP一数据库时,发生如下错误:

SQL> conn /as sysdba
Connected to an idle instance.
SQL> startup
ORACLE instance started.

Total System Global Area 276824064 bytes
Fixed Size 778736 bytes
Variable Size 137371152 bytes
Database Buffers 138412032 bytes
Redo Buffers 262144 bytes
ORA-01102: cannot mount database in EXCLUSIVE mode

SQL> shutdown immediate
ORA-01507: database not mounted

ORACLE instance shut down.

GOOGLE一下,发现是lk文件造成的,该文件位于ORALCE_HOME下的dbs目录下,马上检查该文件:

[root@qa-oracle dbs]# fuser -u lkNDMSQA
lkNDMSQA: 6666(oracle) 6668(oracle) 6670(oracle) 6672(oracle) 6674(oracle) 6676(oracle) 6678(oracle) 6680(oracle) 6690(oracle) 6692(oracle) 6694(oracle) 6696(oracle) 6737(oracle) 6830(oracle)

果然该文件没释放,用fuser命令kill掉:

[root@qa-oracle dbs]# fuser -k lkNDMSQA
lkNDMSQA: 6666 6668 6670 6672 6674 6676 6678 6680 6690 6692 6694 6696 6737 6830
[root@qa-oracle dbs]# fuser -u lkNDMSQA

然后:

SQL> startup
ORACLE instance started.

Total System Global Area 276824064 bytes
Fixed Size 778736 bytes
Variable Size 137371152 bytes
Database Buffers 138412032 bytes
Redo Buffers 262144 bytes
Database mounted.
Database opened.
SQL>

数据库成功OPEN.

关于该错误更详细的介绍如下:原文链接:http://www.hellodba.com/cases/case-unexception_down.htm

数据库异常关闭后无法启动问题处理一例

作者: fuyuncat

来源: www.HelloDBA.com

某系统突然掉电,系统启动后发现Oracle无法启动。启动时报如下错误:

ORA-01102 cannot mount database in EXCLUSIVE mode
出现1102错误可能有以下几种可能:

一、在HA系统中,已经有其他节点启动了实例,将双机共享的资源(如磁盘阵列上的裸设备)占用了;

二、说明Oracle被异常关闭时,有资源没有被释放,一般有以下几种可能,

1、 Oracle的共享内存段或信号量没有被释放;

2、 Oracle的后台进程(如SMON、PMON、DBWn等)没有被关闭;

3、 用于锁内存的文件lk和sgadef.dbf文件没有被删除。

首先,虽然我们的系统是HA系统,但是备节点的实例始终处在关闭状态,这点通过在备节点上查数据库状态可以证实。

其次、是因系统掉电引起数据库宕机的,系统在接电后被重启,因此我们排除了第二种可能种的1、2点。最可疑的就是第3点了。

查$ORACLE_HOME/dbs目录:

$ cd $ORACLE_HOME/dbs
$ ls sgadef*
sgadef* not found
$ ls lk*
lkORA92
果然,lk文件没有被删除。将它删除掉

$ rm lk*
再启动数据库,成功。

如果怀疑是共享内存没有被释放,可以用以下命令查看:

$ipcs -mop
IPC status from /dev/kmem as of Thu Jul 6 14:41:43 2006
T ID KEY MODE OWNER GROUP NATTCH CPID LPID
Shared Memory:
m 0 0×411c29d6 –rw-rw-rw- root root 0 899 899
m 1 0×4e0c0002 –rw-rw-rw- root root 2 899 901
m 2 0×4120007a –rw-rw-rw- root root 2 899 901
m 458755 0×0c6629c9 –rw-r—– root sys 2 9113 17065
m 4 0×06347849 –rw-rw-rw- root root 1 1661 9150
m 65541 0xffffffff –rw-r–r– root root 0 1659 1659
m 524294 0×5e100011 –rw——- root root 1 1811 1811
m 851975 0×5fe48aa4 –rw-r—– oracle oinstall 66 2017 25076
然后它ID号清除共享内存段:

$ipcrm –m 851975
对于信号量,可以用以下命令查看:

$ ipcs -sop
IPC status from /dev/kmem as of Thu Jul 6 14:44:16 2006
T ID KEY MODE OWNER GROUP
Semaphores:
s 0 0×4f1c0139 –ra——- root root
… …
s 14 0×6c200ad8 –ra-ra-ra- root root
s 15 0×6d200ad8 –ra-ra-ra- root root
s 16 0×6f200ad8 –ra-ra-ra- root root
s 17 0xffffffff –ra-r–r– root root
s 18 0×410c05c7 –ra-ra-ra- root root
s 19 0×00446f6e –ra-r–r– root root
s 20 0×00446f6d –ra-r–r– root root
s 21 0×00000001 –ra-ra-ra- root root
s 45078 0×67e72b58 –ra-r—– oracle oinstall
根据信号量ID,用以下命令清除信号量:

$ipcrm -s 45078
如果是Oracle进程没有关闭,用以下命令查出存在的oracle进程:

$ ps -ef|grep ora
oracle 29976 1 0 Jun 22 ? 0:52 ora_dbw0_ora92
oracle 29978 1 0 Jun 22 ? 0:51 ora_dbw1_ora92
oracle 5128 1 0 Jul 5 ? 0:00 oracleora92 (LOCAL=NO)
… …
然后用kill -9命令杀掉进程

$kill -9
总结:

当发生1102错误时,可以按照以下流程检查、排错:

1.如果是HA系统,检查其他节点是否已经启动实例;
2.检查Oracle进程是否存在,如果存在则杀掉进程;
3.检查信号量是否存在,如果存在,则清除信号量;
4.检查共享内存段是否存在,如果存在,则清除共享内存段;
5.检查锁内存文件lk和sgadef.dbf是否存在,如果存在,则删除。

2008年7月18日 星期五

Pool Module

sqlrelay
mysql_proxy

2008年7月11日 星期五

Using MySQL with memcached

http://dev.mysql.com/doc/refman/5.0/en/ha-memcached.html

2008年7月8日 星期二

Oracle Backup Recovery Solutions

http://www.qudong.com/soft/program/Oracle/shujuguanli/20080319/2537.html

http://www.qudong.com/soft/program/Oracle/shujuguanli/list_155_2.html

DBA Task

1.Evaluate Server and Install
2.Plan,Implement,Create,Open Database
3.Security (User and Database)
4.Tuning (SQL and Performance)
5.Backup and Recovery
6.Other : AP,RAC,TOOLS,STREAM,DATA GUARD

2008年6月13日 星期五

select * from goods_file
AS OF TIMESTAMP timestamp'2008-06-12 14:53:47'
where g_no = 11080531367948

2008年6月11日 星期三

Oracle DBCA (Database Configuration Assistant)

Template
1.Data Warehouse
2.Transaction Processing
3.General Purpose


1.Dedicated Server Mode
2.Shared Server Mode

Reset SYS , SYSTEM account default password.

Oracle Instance
1.System Global Area
SGA_MAX_SIZE , DB_CACHE_SIZE , LOG_BUFFER , SHARED_POOL_SIZE , LARGE_POOL_SIZE
2.Background processes

Data Cache Buffer
1.Write List (dirty buffers wait for write to disk)
2.LRU list (free , dirty , pinned buffers)
LRU Least Recently Used
MRU Most Recently Used

Total Size = DB_BLOCK_SIZE(2~32KB) * DB_BLOCK_BUFFERS

Redo Log Buffer (bytes)
Default : Redo Log Buffer = 4 * System Block Size

Share Pool (SHARED_POOL_SIZE = 8 MB in 32-bit , 6 MB in 64-bit system )
1. Library cache
Share SQL Area (SQL parse tree , execution plan)
Private SQL Area
PL/SQL Program Unit
2. Dictionary cache
parse information like table , view name , column name , data type
user privileges

DBWn - Database Writer
write dirty blocks from Data Cache Buffer to data files. => checkpoint
default only DBW0
btw in OLTP , update busy
DBW1~DBW9 is prefered.


LGWR - Log Writer
Write to redo log files
When
1. transaction commited
2. Auto Writing each 3 seconds.
3. free size of Redo log buffer is less than 1/3.
4. Before DBWn write dirty blocks to data files
Write - ahead protocol :
if LGWR write Redo data to redo logs finished
DBWn write dirty blocks to data files
else
Call LGWR write Redo data to redo logs
Then DBWn do its work.

SMON - System Monitor
Database Start Recovery checking
1. After Database restart , nessesary recovery activities.
2. Release not used temporary segments.
3. Collect and manage free extents
4. Recovery abort transaction.

PMON - Process Monitor
1. Recovery abort Process
2. Clear Data Buffer cache Unused block, reset transaction table status,
Unlock row , remove terminated process ID.

CKPT - Checkpoint
1. make sure MRU Dirty Data will write to data file regularly.
2. when instance recovery , can ignore the record before the currently checkpoint.
3. if(checkpoint finished)
CKPT call DBWn;
Then update control file and header of data file.
RECO (Recover)
handle transaction in Cluster database.
in-doubt transaction . transaction between servers.

ARCn (Archiver) (LOG_ARCHIVE_MAX_PROCESSES LIMIT IS 10 OR ALTER SYSTEM to change)
log switch. Archived logs.
indeed, Oracle will judge it automatically.

2008年6月9日 星期一

MySQL Index Building Tips

1. 資料種類較少 ex 男, 女 的index 在複合 index 中 放越前越好 (B-Tree divide)

2. 會按 index 建立的時間來吃, 吃到就不會繼續往下找,即使有更好的index~~

3. where date_format('A') = '20080723'
mod('A') = 5
=> 在設計之初 , 就要規劃好 避免在where 中 轉 格式.

4. where A is NULL => 會 full table scan
可以放default , ex: '0' => where A = 0 or "NULL" => where A = 'NULL'

2008年6月2日 星期一

Oracle Text

Form http://www.oracle.com/technology/products/text/index.html
Oracle Text
Oracle Text uses standard SQL to index, search, and analyze text and documents stored in the Oracle database, in files, and on the web. Oracle Text can perform linguistic analysis on documents, as well as search text using a variety of strategies including keyword searching, context queries, Boolean operations, pattern matching, mixed thematic queries, HTML/XML section searching, and so on. It can render search results in various formats including unformatted text, HTML with term highlighting, and original document format. Oracle Text supports multiple languages and uses advanced relevance-ranking technology to improve search quality. Oracle Text also offers advanced features like classification, clustering, and support for information visualization metaphors.

Oracle TimesTen In-Memory Database

http://www.oracle.com/timesten/index.html

Database Built in Memory : Oracle TimesTen

2008年5月27日 星期二

Select * From ap2_class_mapping Where class_id in ('0002','0012')
=> 會吃 index
Select * From ap2_class_mapping Where class_id in (0002,0012)
=> Full Scan

=> 有沒有單引號差很多

2008年5月17日 星期六

From ITHome
MySQL漸有大型企業採用,取得認證就業機會高
文/黃彥棻 (記者) 2008-02-01

MySQL在推出5.0版本時,將證照名稱正名,可以從證照看出是資料庫開發或者是資料庫管理員,目前臺灣若要考CMDEV和CMDBA,可以到全省VUE考試中心線上報名及考試。

由開放原始碼撰寫的資料庫產品MySQL,日前雖然被昇陽(Sun)併購,但因為MySQL有免費版和商業版,成為臺灣中小企業和個人用戶使用頻率最高的資料庫產品。但近年有不少大型企業開始評估或已經使用MySQL後,也使得取得MySQL證照的IT人,工作機會水漲船高。

MySQL資料庫因為是開放源碼撰寫的產品,對於許多SOHO或者是中小企業主而言,免費又兼具效能的MySQL,往往是第一也是唯一的資料庫選擇。巨匠電腦PHP與MySQL課程講師梁國亮表示,近來也發現有一些系統廠商或者是中小企業主,將MySQL作為單純進銷存系統或者是ERP(企業資源規畫)的後端資料庫使用。此外,也發現有一些中大型的網站或者是公家機關,也開始使用MySQL,「使用對象不再侷限以往的中小企業或者是SOHO族。」梁國亮說。

不只如此,梁國亮也觀察到,許多重量級廠商已經在部分的產品線上使用MySQL,例如電信業者彙整繳費資料到前端資料庫,就是使用MySQL;搜尋引擎業者某一些前端的資料庫,或者是某些大型的電子商務網站,甚至是美國最著名的網路書店Amazon,都有部分使用MySQL資料庫。

除了這些大型企業也開始使用MySQL資料庫外,梁國亮自身的教學經驗中也發現,有某家DRAM廠商,正在積極評估是否可以部分採用較為便宜的 MySQL資料庫,作為生產數據分析之用。他進一步表示,這家企業主對於MySQL的課程,要求到非常進階的使用功能,對於效能的調校與掌握,也要求務必徹底了解。梁國亮表示,這間DRAM業者為了降低成本,開始評估採用MySQL資料庫的可能性,如果效能上能夠符合該業者的需求,「光是1年資料庫軟體的授權費用,就可以節省上千萬元,」梁國亮說。

目前MySQL有3張相關證照,分別是基礎開發的CMDEV(Certified MySQL Developer)、資料庫管理員的CMDBA(Certified MySQL DBA)和高階叢集運算的CMCDBA(Certified MySQL Cluster DBA)。梁國亮目前已經取得CMDEV和CMDBA兩張證照,而CMCDBA則是去年下半年才推出的新證照。

梁國亮指出,目前證照的名稱是去年底MySQL升級到5.0版後,才重新命名的,原本在MySQL 4.0版本中,分成Core和Profession的兩張證照,難以從證照名稱上就看出原來Core就是資料庫開發工程師,Profession就是資料庫管理員。所以在MySQL 5.0版本中,才從善如流,從證照名稱就可以看出特色。

CMDEV和CMDBA都需要考2科上機的實機考試,單選題和複選題都有。梁國亮經驗表示,在考取CMDEV證照時,因為偏重開發的功能,「考生對於SQL的語法必須非常的了解,」梁國亮依自己考試經驗表示,考題上常出現考你一串語法後,問考生之後的執行結果為何,「這必須對於SQL語法非常熟悉。」他說。

至於CMDBA的考試上,梁國亮表示,主要是考驗考生對資料庫管理的概念和相關程序的了解,不論是使用者、權限管理,資料庫維護,包含備份、還原、目錄(Index)或重整等,都必須相當熟悉。他說,因為考試重視程序,考題就會有類似「資料庫壞了,正確的挽救程序應該如何執行?」的題目。

梁國亮表示,對於一個資料庫管理員而言,MySQL只是其中的一個產品類型,下一步發展的方向,不論是微軟的SQL Server 2005或者是大型的商用資料庫軟體如甲骨文或SAP等,都是進階學習的選擇。

目前臺灣若要考CMDEV和CMDBA,可以到全省VUE考試中心線上報名及考試。文⊙黃彥棻
from http://blog.pixnet.net/miles0722/post/8396830
MySQL截至目前為止有四種認證:

Certified MySQL Associate (CMA): MySQL for Beginners
Certified MySQL 5.0 Developer (CMDEV): MySQL 5.0 for Developers
Certified MySQL 5.0 Database Administrator (CMDBA): MySQL 5.0 for DBAs
Certified MySQL 5.1 Cluster Database Administrator (CMCDBA): MySQL Cluster for High Availability

其中 CMA只需通過一科,而CMEDV與CMDBA皆需通過兩科,CMCDBA則需先有CMDBA認證,加上通過一科才能擁有。

每次考試皆是US$200。

Exam Exam Code Questions Passing Score Exam time CMA

010-* 50 36-38 60 minutes Developer-I

003-* 70 42-44 90 minutes Developer-II

004-* 70 42-44 90 minutes DBA-I

005-* 70 44-46 90 minutes DBA-II

006-* 70 44-46 90 minutes Cluster DBA

009-* 70 42-44 90 minutes Core to Developer upgr.

007-* 60 34-36 75 minutes Professional to DBA upgr.

008-* 60 34-36 75 minutes

除了CMCDBA,其他三個認證可以買 MySQL 5.0 Certification Study Guide 自修,天瓏書局可以買得到。此書依據Developer-I、Developer-II、DBA-I與DBA-II分為四大部份四十二章。若是要考CMA,依據官方網站的說明,則需選讀此書的
Chapter 1: Sections 1.1 and 1.2
Chapter 5: Sections 5.1 through 5.4, 5.5 (but not 5.5.2 and 5.5.3), 5.6 and 5.7
Chapter 7: All
Chapter 8: All
Chapter 9: All, except for 9.6
Chapter 10: 10.5
Chapter 11: All
Chapter 14: Sections 14.1, 14.2 (but not 14.2.1 through 14.2.3), 14.3, 14.4, 14.6
Chapter 15: All, except 15.2.3 and 15.3.1
Chapter 29: Parts 29.4.2 and 29.4.3
Chapter 32: Section 32.4
網站上建議下列章節也要讀
Chapter 2 : All
Chapter 5: parts 5.4.1, 5.4.3
Chapter 20: 20.3
Chapter 25: 25.5, 25.6
Chapter 29: 29.4.6
Chapter 31: All



若是要考CMCDBA,則是要買 MySQL Cluster Certification Study Guide 一書。

附帶一提的是,MySQL 5.0 Certification Study Guide的後面書皮內側有一組號碼,第一次考試使用可以打75折,還不錯說~~不過可是有期限的哦,在最下面一行有寫,小小的字。

點這可以看到世界上有多少人拿到MySQL認證。

MySQL官方網站

2008年5月15日 星期四

from
http://www.itpub.net/114023.html
bitmap 的一点探究

1:bitmap 索引是分段存储的,也就是说很多条记录可能是分做了N段来存储,也就是有N个begin/end ,当新的记录 insert 而使用以前未曾使用过的物理地址的时候,会产生一个bitmap 段来存储,就算只有一条记录

2: 当删除一条记录的时候,在bitmap 索引上做了一个delete 的标记并用一新的记录来标记了,下面请看具体的演示

3: 当 dml发生的时候,会lock住某个值的存储bit的那一rowid所在的记录,参考下面的 row 中 lock ,这样显然会影响并发


SQL> create table tn(a number, b number);

Table created.

SQL> insert into tn select rownum,mod(rownum,5) from all_objects where rownum < 21;

20 rows created.

SQL> commit;

Commit complete.

SQL> create bitmap index tn_bitmap on tn(b);

Index created.

SQL> exec show_space('tn_bitmap',user,'INDEX');
Free Blocks.............................0
Total Blocks............................16
Total Bytes.............................131072
Unused Blocks...........................14
Unused Bytes............................114688
Last Used Ext FileId....................3
Last Used Ext BlockId...................1954
Last Used Block.........................2

PL/SQL procedure successfully completed.

SQL> select * from tn;

A B
---------- ----------
1 1
2 2
3 3
4 4
5 0
6 1
7 2
8 3
9 4
10 0
11 1

A B
---------- ----------
12 2
13 3
14 4
15 0
16 1
17 2
18 3
19 4
20 0

20 rows selected.

SQL> alter system dump datafile 3 block 1955;

System altered.

Block header dump: 0x00c007a3
Object id on Block? Y
seg/obj: 0x66da csc: 0x00.18a0d77 itc: 2 flg: - typ: 2 - INDEX
fsl: 0 fnx: 0x0 ver: 0x01

Itl Xid Uba Flag Lck Scn/Fsc
0x01 xid: 0x0000.000.00000000 uba: 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000
0x02 xid: 0x0002.040.000000ea uba: 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000

Leaf block dump
===============
header address 125987932=0x7826c5c
kdxcolev 0
kdxcolok 0
kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y
kdxconco 4
kdxcosdc 0
kdxconro 5
kdxcofbo 46=0x2e
kdxcofeo 7918=0x1eee
kdxcoavs 7872
kdxlespl 0
kdxlende 0
kdxlenxt 0=0x0
kdxleprv 0=0x0
kdxledsz 0
kdxlebksz 8036
row#0[8013] flag: -----, lock: 0
col 0; len 1; (1): 80 ---表示值为0
col 1; len 6; (6): 00 c0 7e 03 00 00 ---rowid 起点的block和行号
col 2; len 6; (6): 00 c0 7e 03 00 17 ---rowid 结束的block和行号,注意17 = 16+7 = 23 ,也就是下面转换后的有效位置截止到23bit
col 3; len 4; (4): ca 10 42 08 ---把该值按照16进制数转化为 11001010 (首字节不表示rowid信息) 00010000 01000010 00001000 ,
凡是从起点到结束点内的1表示该值存在,这里有 一个必须要注意的问题是,这样转化后的位置并不是真实的物理位置,在每个字节内部bit还要颠倒一下顺序,首字节不表示位置信息
也就是说上面的应该转换为 00001000 01000010 00010000 ,发现正好每5个存在一个值为0的记录
row#1[7990] flag: -----, lock: 0
col 0; len 2; (2): c1 02 ---表示值为1
col 1; len 6; (6): 00 c0 7e 03 00 00
col 2; len 6; (6): 00 c0 7e 03 00 0f ---注意这里是f,也就是一共只有16位,因为1是第一条记录开始的,在16的位置就已经有5条了
col 3; len 3; (3): c9 21 84 注意这里的 21 84 正好16位,根据上面描述的规则转换后就是 10000100 00100001,4个1正好表示记录
row#2[7966] flag: -----, lock: 0
col 0; len 2; (2): c1 03 ---表示值为2
col 1; len 6; (6): 00 c0 7e 03 00 00
col 2; len 6; (6): 00 c0 7e 03 00 17
col 3; len 4; (4): ca 42 08 01
row#3[7942] flag: -----, lock: 0
col 0; len 2; (2): c1 04 ---表示值为3
col 1; len 6; (6): 00 c0 7e 03 00 00
col 2; len 6; (6): 00 c0 7e 03 00 17
col 3; len 4; (4): ca 84 10 02
row#4[7918] flag: -----, lock: 0
col 0; len 2; (2): c1 05 ---表示值为4
col 1; len 6; (6): 00 c0 7e 03 00 00
col 2; len 6; (6): 00 c0 7e 03 00 17
col 3; len 4; (4): ca 08 21 04
----- end of leaf block dump -----
End dump data blocks tsn: 2 file#: 3 minblk 1955 maxblk 1955



SQL> delete from tn where a = 2;

1 row deleted.

SQL> commit;

Commit complete.

SQL> alter system dump datafile 3 block 1955;

System altered.

SQL>

Block header dump: 0x00c007a3
Object id on Block? Y
seg/obj: 0x66da csc: 0x00.18a0d77 itc: 2 flg: - typ: 2 - INDEX
fsl: 0 fnx: 0x0 ver: 0x01

Itl Xid Uba Flag Lck Scn/Fsc
0x01 xid: 0x0000.000.00000000 uba: 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000
0x02 xid: 0x0003.047.000000e9 uba: 0x00800dba.00d9.1f --U- 2 fsc 0x001a.018a0d7d

Leaf block dump
===============
header address 125987932=0x7826c5c
kdxcolev 0
kdxcolok 0
kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y
kdxconco 4
kdxcosdc 0
kdxconro 6
kdxcofbo 48=0x30
kdxcofeo 7894=0x1ed6
kdxcoavs 7846
kdxlespl 0
kdxlende 1
kdxlenxt 0=0x0
kdxleprv 0=0x0
kdxledsz 0
kdxlebksz 8036
row#0[8013] flag: -----, lock: 0
col 0; len 1; (1): 80
col 1; len 6; (6): 00 c0 7e 03 00 00
col 2; len 6; (6): 00 c0 7e 03 00 17
col 3; len 4; (4): ca 10 42 08
row#1[7990] flag: -----, lock: 0
col 0; len 2; (2): c1 02
col 1; len 6; (6): 00 c0 7e 03 00 00
col 2; len 6; (6): 00 c0 7e 03 00 0f
col 3; len 3; (3): c9 21 84
row#2[7894] flag: -----, lock: 2 ---这是删除后的拷贝,我们发现删除的时候该行已经加锁 lock : 2
col 0; len 2; (2): c1 03
col 1; len 6; (6): 00 c0 7e 03 00 00
col 2; len 6; (6): 00 c0 7e 03 00 17
col 3; len 4; (4): ca 40 08 01 ---我们发现 ca 42 已经变成 ca 40 ,也就是已经少掉一位bit了,正好是删除的那一条记录
row#3[7966] flag: ---D-, lock: 2 ---这里我们发现值为2的记录已经有删除过的 ---D- ,D表示delete
col 0; len 2; (2): c1 03
col 1; len 6; (6): 00 c0 7e 03 00 00
col 2; len 6; (6): 00 c0 7e 03 00 17
col 3; len 4; (4): ca 42 08 01
row#4[7942] flag: -----, lock: 0
col 0; len 2; (2): c1 04
col 1; len 6; (6): 00 c0 7e 03 00 00
col 2; len 6; (6): 00 c0 7e 03 00 17
col 3; len 4; (4): ca 84 10 02
row#5[7918] flag: -----, lock: 0
col 0; len 2; (2): c1 05
col 1; len 6; (6): 00 c0 7e 03 00 00
col 2; len 6; (6): 00 c0 7e 03 00 17
col 3; len 4; (4): ca 08 21 04
----- end of leaf block dump -----
End dump data blocks tsn: 2 file#: 3 minblk 1955 maxblk 1955
再继续补充

首先truncate 表所有数据
truncate table tn;

SQL> exec show_space('tn_bitmap','i');
Free Blocks.............................0
Total Blocks............................16
Total Bytes.............................131072
Unused Blocks...........................14
Unused Bytes............................114688
Last Used Ext FileId....................3
Last Used Ext BlockId...................1954
Last Used Block.........................2

PL/SQL procedure successfully completed.

可以看出索引是空的

然后插入一条数据

SQL> insert into tn values(1,1);

1 row created.

SQL> commit;

Commit complete.

SQL> alter system dump datafile 3 block 1955;

System altered.



row#0[8009] flag: -----, lock: 2
col 0; len 2; (2): c1 02
col 1; len 6; (6): 00 c0 7e 03 00 00
col 2; len 6; (6): 00 c0 7e 03 00 07
col 3; len 1; (1): 00
row#1[8030] flag: ---D-, lock: 2
col 0; NULL
col 1; NULL
col 2; NULL
col 3; NULL




SQL> insert into tn values(1,1);

1 row created.

SQL> commit;

Commit complete.

SQL> alter system dump datafile 3 block 1955;

System altered.



row#0[8009] flag: ---D-, lock: 2 -- 标记删除,下面一份是拷贝
col 0; len 2; (2): c1 02
col 1; len 6; (6): 00 c0 7e 03 00 00
col 2; len 6; (6): 00 c0 7e 03 00 07
col 3; len 1; (1): 00
row#1[7987] flag: -----, lock: 2
col 0; len 2; (2): c1 02
col 1; len 6; (6): 00 c0 7e 03 00 00 00---07 正好表示8 rows
col 2; len 6; (6): 00 c0 7e 03 00 07
col 3; len 2; (2): c8 03 -- 03 正好表示2条记录被插入



SQL> insert into tn values(1,1);

1 row created.

SQL> alter system dump datafile 3 block 1955;

System altered.

row#0[7987] flag: ---D-, lock: 2
col 0; len 2; (2): c1 02
col 1; len 6; (6): 00 c0 7e 03 00 00
col 2; len 6; (6): 00 c0 7e 03 00 07
col 3; len 2; (2): c8 03
row#1[7965] flag: -----, lock: 2
col 0; len 2; (2): c1 02
col 1; len 6; (6): 00 c0 7e 03 00 00
col 2; len 6; (6): 00 c0 7e 03 00 07
col 3; len 2; (2): c8 07 -- 07 正好表示3条记录被插入



SQL> insert into tn values(1,1);

1 row created.

SQL> insert into tn values(1,1);

1 row created.

SQL> insert into tn values(1,1);

1 row created.

SQL> insert into tn values(1,1);

1 row created.

SQL> insert into tn values(1,1);

1 row created.

SQL> commit;

Commit complete.

SQL> alter system dump datafile 3 block 1955;

System altered.

我们在同一个session中同一个事务连续插入5条记录,发现在bitmap中居然做了5个拷贝

row#0[7987] flag: ---D-, lock: 2
col 0; len 2; (2): c1 02
col 1; len 6; (6): 00 c0 7e 03 00 00
col 2; len 6; (6): 00 c0 7e 03 00 07
col 3; len 2; (2): c8 03
row#1[7965] flag: ---D-, lock: 2
col 0; len 2; (2): c1 02
col 1; len 6; (6): 00 c0 7e 03 00 00
col 2; len 6; (6): 00 c0 7e 03 00 07
col 3; len 2; (2): c8 07
row#2[7943] flag: ---D-, lock: 2
col 0; len 2; (2): c1 02
col 1; len 6; (6): 00 c0 7e 03 00 00
col 2; len 6; (6): 00 c0 7e 03 00 07
col 3; len 2; (2): c8 0f
row#3[7921] flag: ---D-, lock: 2
col 0; len 2; (2): c1 02
col 1; len 6; (6): 00 c0 7e 03 00 00
col 2; len 6; (6): 00 c0 7e 03 00 07
col 3; len 2; (2): c8 1f
row#4[7899] flag: ---D-, lock: 2
col 0; len 2; (2): c1 02
col 1; len 6; (6): 00 c0 7e 03 00 00
col 2; len 6; (6): 00 c0 7e 03 00 07
col 3; len 2; (2): c8 3f
row#5[7877] flag: ---D-, lock: 2
col 0; len 2; (2): c1 02
col 1; len 6; (6): 00 c0 7e 03 00 00
col 2; len 6; (6): 00 c0 7e 03 00 07
col 3; len 2; (2): c8 7f
row#6[7855] flag: -----, lock: 2
col 0; len 2; (2): c1 02
col 1; len 6; (6): 00 c0 7e 03 00 00
col 2; len 6; (6): 00 c0 7e 03 00 07
col 3; len 2; (2): c8 ff -- ff 正好表示8条记录被插入


SQL> insert into tn values(1,1);

1 row created.

SQL> commit;

Commit complete.

SQL> alter system dump datafile 3 block 1955;

System altered.

SQL>

-- 上一个bitmap段存储表示8条记录,我们再插入第9条记录再来看

row#0[7855] flag: -----, lock: 2
col 0; len 2; (2): c1 02
col 1; len 6; (6): 00 c0 7e 03 00 00
col 2; len 6; (6): 00 c0 7e 03 00 07
col 3; len 2; (2): c8 ff -- 8条记录已满,也把前面的前8条的多拷贝给清除掉了
row#1[7834] flag: -----, lock: 2
col 0; len 2; (2): c1 02
col 1; len 6; (6): 00 c0 7e 03 00 08
col 2; len 6; (6): 00 c0 7e 03 00 0f
col 3; len 1; (1): 00 新插入的第9条记录被新的从 08 -- 0f 这8个字节用来存储


综合上面的实验可以看出,当单条insert发生的时候,会以8条记录为一个bitmap row 来存储,这正好是一个字节的bit,并且就算是
相同事务中的insert也会导致大量的拷贝和lock产生,严重影响性能,甚至可能发生行迁移等严重问题,所以在经常发生变化的表中
我们不应该采用 bitmap index ,当发生update 的时候情形更为复杂,暂时不予讨论了
///////////////
SQL> truncate table tn;

表已截掉。

SQL> exec show_space('tn_bitmap',user,'INDEX');
Free Blocks.............................0
Total Blocks............................3
Total Bytes.............................12288
Unused Blocks...........................1
Unused Bytes............................4096
Last Used Ext FileId....................1
Last Used Ext BlockId...................26474
Last Used Block.........................2

PL/SQL 过程已成功完成。

SQL> alter system dump datafile 1 block 26475;

系统已更改。

Leaf block dump
===============
header address 83060828=0x4f3685c
kdxcolev 0
KDXCOLEV Flags = - - -
kdxcolok 0
kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y
kdxconco 4
kdxcosdc 0
kdxconro 0
kdxcofbo 36=0x24
kdxcofeo 3940=0xf64
kdxcoavs 3904
kdxlespl 0
kdxlende 0
kdxlenxt 0=0x0
kdxleprv 0=0x0
kdxledsz 0
kdxlebksz 3940
----- end of leaf block dump -----
End dump data blocks tsn: 0 file#: 1 minblk 26475 maxblk 26475
索引已经清空

SQL> insert into tn values (1, 1);

已创建 1 行。

SQL> /

已创建 1 行。

SQL> /

已创建 1 行。

SQL> /

已创建 1 行。

SQL> /

已创建 1 行。

SQL> /

已创建 1 行。

SQL> /

已创建 1 行。

SQL> /

已创建 1 行。

SQL> /

已创建 1 行。

SQL> /

已创建 1 行。

依次插入10行数据。

SQL> commit;

提交完成。

SQL> alter system dump datafile 1 block 26475;

系统已更改。

Leaf block dump
===============
header address 83060828=0x4f3685c
kdxcolev 0
KDXCOLEV Flags = - - -
kdxcolok 0
kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y
kdxconco 4
kdxcosdc 0
kdxconro 11
kdxcofbo 58=0x3a
kdxcofeo 3716=0xe84
kdxcoavs 3658
kdxlespl 0
kdxlende 9
kdxlenxt 0=0x0
kdxleprv 0=0x0
kdxledsz 0
kdxlebksz 3940
row#0[3913] flag: ---D-, lock: 2
col 0; len 2; (2): c1 02
col 1; len 6; (6): 00 40 67 68 00 00
col 2; len 6; (6): 00 40 67 68 00 07
col 3; len 1; (1): 00
row#1[3891] flag: ---D-, lock: 2
col 0; len 2; (2): c1 02
col 1; len 6; (6): 00 40 67 68 00 00
col 2; len 6; (6): 00 40 67 68 00 07
col 3; len 2; (2): c8 03
row#2[3869] flag: ---D-, lock: 2
col 0; len 2; (2): c1 02
col 1; len 6; (6): 00 40 67 68 00 00
col 2; len 6; (6): 00 40 67 68 00 07
col 3; len 2; (2): c8 07
row#3[3847] flag: ---D-, lock: 2
col 0; len 2; (2): c1 02
col 1; len 6; (6): 00 40 67 68 00 00
col 2; len 6; (6): 00 40 67 68 00 07
col 3; len 2; (2): c8 0f
row#4[3825] flag: ---D-, lock: 2
col 0; len 2; (2): c1 02
col 1; len 6; (6): 00 40 67 68 00 00
col 2; len 6; (6): 00 40 67 68 00 07
col 3; len 2; (2): c8 1f
row#5[3803] flag: ---D-, lock: 2
col 0; len 2; (2): c1 02
col 1; len 6; (6): 00 40 67 68 00 00
col 2; len 6; (6): 00 40 67 68 00 07
col 3; len 2; (2): c8 3f
row#6[3781] flag: ---D-, lock: 2
col 0; len 2; (2): c1 02
col 1; len 6; (6): 00 40 67 68 00 00
col 2; len 6; (6): 00 40 67 68 00 07
col 3; len 2; (2): c8 7f
row#7[3759] flag: -----, lock: 2
col 0; len 2; (2): c1 02
col 1; len 6; (6): 00 40 67 68 00 00
col 2; len 6; (6): 00 40 67 68 00 07
col 3; len 2; (2): c8 ff
row#8[3738] flag: ---D-, lock: 2
col 0; len 2; (2): c1 02
col 1; len 6; (6): 00 40 67 68 00 08
col 2; len 6; (6): 00 40 67 68 00 0f
col 3; len 1; (1): 00
row#9[3716] flag: -----, lock: 2
col 0; len 2; (2): c1 02
col 1; len 6; (6): 00 40 67 68 00 08
col 2; len 6; (6): 00 40 67 68 00 0f
col 3; len 2; (2): c8 03
row#10[3934] flag: ---D-, lock: 2
col 0; NULL
col 1; NULL
col 2; NULL
col 3; NULL
----- end of leaf block dump -----
End dump data blocks tsn: 0 file#: 1 minblk 26475 maxblk 26475

oracle对每次插入的数据都进行索引。


SQL> truncate table tn;

表已截掉。

SQL> alter system dump datafile 1 block 26475;

系统已更改。

Leaf block dump
===============
header address 83060828=0x4f3685c
kdxcolev 0
KDXCOLEV Flags = - - -
kdxcolok 0
kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y
kdxconco 4
kdxcosdc 0
kdxconro 0
kdxcofbo 36=0x24
kdxcofeo 3940=0xf64
kdxcoavs 3904
kdxlespl 0
kdxlende 0
kdxlenxt 0=0x0
kdxleprv 0=0x0
kdxledsz 0
kdxlebksz 3940
----- end of leaf block dump -----

一次性插入10条数据
SQL> insert into tn select 1,1 from user_objects where rownum < 11;

已创建10行。

SQL> commit;

提交完成。

SQL> alter system dump datafile 1 block 26475;

系统已更改。

Leaf block dump
===============
header address 83060828=0x4f3685c
kdxcolev 0
KDXCOLEV Flags = - - -
kdxcolok 0
kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y
kdxconco 4
kdxcosdc 0
kdxconro 2
kdxcofbo 40=0x28
kdxcofeo 3911=0xf47
kdxcoavs 3871
kdxlespl 0
kdxlende 1
kdxlenxt 0=0x0
kdxleprv 0=0x0
kdxledsz 0
kdxlebksz 3940
row#0[3911] flag: -----, lock: 2
col 0; len 2; (2): c1 02
col 1; len 6; (6): 00 40 67 68 00 00
col 2; len 6; (6): 00 40 67 68 00 0f
col 3; len 3; (3): c9 ff 03 一次性插入的数据,oracle会对整批数据进行bitmap索引。
row#1[3934] flag: ---D-, lock: 2
col 0; NULL
col 1; NULL
col 2; NULL
col 3; NULL
----- end of leaf block dump -----
End dump data blocks tsn: 0 file#: 1 minblk 26475 maxblk 26475

因此我认为对于包含bitmap索引的表应当减少对数据库操作的数量。运用批量入库的方法会使性能得到较大的提高。

有什么不对的地方还请指正。


my reply:

综合上面的实验可以看出,当单条insert发生的时候,会以8条记录为一个bitmap row 来存储,这正好是一个字节的bit,并且就算是
相同事务中的insert也会导致大量的拷贝和lock产生,严重影响性能,甚至可能发生行迁移等严重问题,所以在经常发生变化的表中
我们不应该采用 bitmap index ,当发生update 的时候情形更为复杂,暂时不予讨论了



结合
前面的第一条:
:bitmap 索引是分段存储的,也就是说很多条记录可能是分做了N段来存储,也就是有N个begin/end ,当新的记录 insert 而使用以前未曾使用过的物理地址的时候,会产生一个bitmap 段来存储,就算只有一条记录


所以我的实验中可能没有很好的做归纳,但是现象都是有的,描述的比较零散



就是说假如你们每天入库 1000万条记录
那创建 bitmap 索引的这个列有多少不同的值,如果有10万个不同的值以上,那采用 bitmap 是否合适就值得考虑了

2008年5月13日 星期二

Oracle Partion

form
http://jzhua.javaeye.com/blog/166078

一、Oracle分区简介
ORACLE的分区是一种处理超大型表、索引等的技术。分区是一种“分而治之”的技术,通过将大表和索引分成可以管理的小块,从而避免了对每个表作为一个大的、单独的对象进行管理,为大量数据提供了可伸缩的性能。分区通过将操作分配给更小的存储单元,减少了需要进行管理操作的时间,并通过增强的并行处理提高了性能,通过屏蔽故障数据的分区,还增加了可用性。
二、Oracle分区优缺点
 优点:
增强可用性:如果表的某个分区出现故障,表在其他分区的数据仍然可用;
维护方便:如果表的某个分区出现故障,需要修复数据,只修复该分区即可;
均衡I/O:可以把不同的分区映射到磁盘以平衡I/O,改善整个系统性能;
改善查询性能:对分区对象的查询可以仅搜索自己关心的分区,提高检索速度。
 缺点:
分区表相关:已经存在的表没有方法可以直接转化为分区表。不过 Oracle 提供了在线重定义表的功能。
三、Oracle分区方法
 范围分区:
范围分区就是对数据表中的某个值的范围进行分区,根据某个值的范围,决定将该数据存储在哪个分区上。如根据序号分区,根据业务记录的创建日期进行分区等。
 Hash分区(散列分区):
散列分区为通过指定分区编号来均匀分布数据的一种分区类型,因为通过在I/O设备上进行散列分区,使得这些分区大小一致。
 List分区(列表分区):
当你需要明确地控制如何将行映射到分区时,就使用列表分区方法。与范围分区和散列分区所不同,列表分区不支持多列分区。如果要将表按列分区,那么分区键就只能由表的一个单独的列组成,然而可以用范围分区或散列分区方法进行分区的所有的列,都可以用列表分区方法进行分区。
 范围-散列分区(复合分区):
有时候我们需要根据范围分区后,每个分区内的数据再散列地分布在几个表空间中,这样我们就要使用复合分区。复合分区是先使用范围分区,然后在每个分区内再使用散列分区的一种分区方法(注意:先一定要进行范围分区)
 范围-列表分区(复合分区):
范围和列表技术的组合,首先对表进行范围分区,然后用列表技术对每个范围分区再次分区。与组合范围-散列分区不同的是,每个子分区的所有内容表示数据的逻辑子集,由适当的范围和列表分区设置来描述。(注意:先一定要进行范围分区)

四、Oracle表分区表操作
--Partitioning 是否为true
select * from v$option s order by s.PARAMETER desc

--创建表空间
CREATE TABLESPACE "PARTION_03"
LOGGING
DATAFILE 'D:\ORACLE\ORADATA\JZHUA\PARTION_03.dbf' SIZE 50M
EXTENT MANAGEMENT LOCAL SEGMENT SPACE MANAGEMENT AUTO

--删除表空间
drop tablespace partion_01


--范围 分区技术
create table Partition_Test
(
PID number not null,
PITEM varchar2(200),
PDATA date not null
)
partition by range(PID)
(
partition part_01 values less than(50000) tablespace dinya_space01,
partition part_02 values less than(100000) tablespace dinya_space02,
partition part_03 values less than(maxvalue) tablespace dinya_space03
)

create table Partition_TTest
(
PID number not null,
PITEM varchar2(200),
PDATA date not null
)
partition by range(PDATA)
(
partition part_t01 values less than(to_date('2004-01-01','yyyy-mm-dd')) tablespace dinya_space01,
partition part_t02 values less than(to_date('2008-01-01','yyyy-mm-dd')) tablespace dinya_space02,
partition part_t03 values less than(maxvalue) tablespace dinya_space03
)

insert into Partition_Test(PID,PITEM,PDATA) select h.id,h.userid,h.rectime from st_handle h

select * from Partition_Test partition(part_01) t where t.pid = '1961'

--hash 分区技术
create table Partition_HashTest
(
PID number not null,
PITEM varchar2(200),
PDATA date not null
)
partition by hash(PID)
(
partition part_h01 tablespace dinya_space01,
partition part_h02 tablespace dinya_space02,
partition part_h03 tablespace dinya_space03
)

insert into Partition_HashTest(PID,PITEM,PDATA) select h.id,h.userid,h.rectime from st_handle h

select * from Partition_HashTest partition(part_h03) t where t.pid = '1961'


--复合分区技术
create table Partition_FHTest
(
PID number not null,
PITEM varchar2(200),
PDATA date not null
)
partition by range(PDATA) subpartition by hash(PID) subpartitions 3 store in (dinya_space01,dinya_space02,dinya_space03)
(
partition part_fh01 values less than(to_date('2004-01-01','yyyy-mm-dd')) tablespace dinya_space01,
partition part_fh02 values less than(to_date('2008-01-01','yyyy-mm-dd')) tablespace dinya_space02,
partition part_fh03 values less than(maxvalue) tablespace dinya_space03
)

insert into Partition_FHTest(PID,PITEM,PDATA) select h.id,h.userid,h.rectime from st_handle h

select * from Partition_FHTest partition(part_fh02) t where t.pid = '1961'

select * from Partition_FHTest partition(part_fh03) t

--速度比较
select * from st_handle h where h.rectime > to_date('2008-01-01','yyyy-mm-dd');

select * from Partition_FHTest partition(part_fh03) t where t.pdata > to_date('2008-01-01','yyyy-mm-dd');


--分区表操作

--增加一个分区
alter table Partition_Test add partition part_05 values less than (10020) tablespace dinya_space03

--查询分区数据
select * from Partition_FHTest partition(part_fh02) t

--修改分区里的数据
update Partition_FHTest partition(part_fh02) t set t.PITEM = 'JZHUA' where t.pid = '1961'

--删除分区里的数据
delete from Partition_FHTest partition(part_fh02) t where t.pid = '1961'

--合并分区
create table Partition_HB
(
PID number not null,
PITEM varchar2(200),
PDATA date not null
)
partition by range(PID)
(
partition part_01 values less than(50000) tablespace dinya_space01,
partition part_02 values less than(100000) tablespace dinya_space02,
partition part_03 values less than(maxvalue) tablespace dinya_space03
)

insert into Partition_HB(PID,PITEM,PDATA) select h.id,h.userid,h.rectime from st_handle h

select * from Partition_HB partition(part_03) t where t.pid = '100001'

alter table Partition_HB merge partitions part_01,part_02 into partition part_02;

--拆分分区
-- spilt partition 分区名 at(这里是一个临界区,比如:50000就是说小于50000的放在part_01,而大于50000的放在part_02中)
alter table Partition_HB split Partition part_02 at (50000) into (Partition part_01 tablespace dinya_space01, Partition part_02 tablespace dinya_space02);

--更改分区名
alter table Partition_HB rename Partition part_01_test to part_02;
五、Oracle索引分区表操作
分区表和一般表一样可以建立索引,分区表可以创建局部索引和全局索引。当分区中出现许多事务并且要保证所有分区中的数据记录的唯一性时采用全局索引。全局索引建立时 global 子句允许指定索引的范围值,这个范围值为索引字段的范围值。其实理论上有3中分区索引。

 Global索引(全局索引):
对于 global 索引,可以选择是否分区,而且索引的分区可以不与表分区相对应。当对分区进行维护操作时,通常会导致全局索引的 Invalid,必须在执行完操作后 Rebuild。Oracle9i 提供了 Update Global Indexes 语句,可以在进行分区维护的同时重建全局索引。
1:索引信息的存放位置与父表的Partition(分区)信息完全不相干。甚至父表是不是分区表都无所谓的。

create index dinya_idx_t on dinya_test(item_id) global partition by range(item_id) (
partition idx_1 values less than (1000) tablespace dinya_space01,
partition idx_2 values less than (10000) tablespace dinya_space02,
partition idx_3 values less than (maxvalue) tablespace dinya_space03
);
2:但是在这种情况下,如果父表是分区表,要删除父表的一个分区都必须要更新Global Index ,否则索引信息不正确
ALTER TABLE TableName DROP PARTITION PartitionName Update Global Indexes

 Local索引(局部索引):

对于 local 索引,每一个表分区对应一个索引分区(就是说一个分区表一个字段只可以建一个局部索引),当表的分区发生变化时,索引的维护由 Oracle 自动进行;
1:索引信息的存放位置依赖于父表的Partition(分区)信息,换句话说创建这样的索引必须保证父表是Partition(分区),索引信息存放在父表的分区所在的表空间。
2:但是仅可以创建在父表为HashTable或者composite分区表的。
3:仅可以创建在父表为HashTable或者composite分区表的。并且指定的分区数目要与父表的分区数目要一致。

create index dinya_idx_t on dinya_test(item_id) local (
partition idx_1 tablespace dinya_space01,
partition idx_2 tablespace dinya_space02,
partition idx_3 tablespace dinya_space03
);

不指定索引分区名直接对整个表建立索引
create index dinya_idx_t on dinya_test(item_id);

2008年5月7日 星期三

有空來 try ~try~
http://msdn.microsoft.com/zh-tw/library/system.data.oracleclient.oracletype(VS.80).aspx
http://www.dba-oracle.com/t_storing_insert_photo_pictures_tables.htm
http://www.dba-oracle.com/t_blob.htm

Oracle基本数据类型存储格式浅析(一)——字符类型
===========================================================
作者: yangtingkun(http://yangtingkun.itpub.net)
发表于: 2004.12.09 23:47
分类: ORACLE
出处: http://yangtingkun.itpub.net/post/468/9287
---------------------------------------------------------------

前一阵看完文档,对oracle的基本数据类型的存储格式有了一些了解,最近有做了一些测试进行了验证。


打算整理总结一下,这一篇主要说明字符类型的存储格式。主要包括char、varchar2和long等几种类型。








SQL> create table test_char (char_col char(10), varchar_col varchar2(10), long_col long);


表已创建。


SQL> insert into test_char values ('abc', '123', ',fd');


已创建 1 行。


SQL> commit;


提交完成。


SQL> select rowid from test_char;


ROWID
------------------
AAAB3LAAFAAAAAgAAA


根据rowid的定义规则,第7~9位是表示的是数据文件,F表示5,而10~15位表示的是在这个数据文件中的第几个BLOCK,g表示32。(rowid编码相当于64进制。用A~Z a~z 0~9 + /共64个字符表示。A表示0,B表示1,……,a表示26,……,0表示52,……,+表示62,/表示63。)


我们根据计算的结果去dump这个block。


SQL> ALTER SYSTEM DUMP DATAFILE 5 BLOCK 32;


系统已更改。


打开产生的trace文件:


data_block_dump,data header at 0x3421064
===============
tsiz: 0x1f98
hsiz: 0x14
pbl: 0x03421064
bdba: 0x01400020
76543210
flag=--------
ntab=1
nrow=1
frre=-1
fsbo=0x14
fseo=0x1f82
avsp=0x1f6e
tosp=0x1f6e
0xe:pti[0] nrow=1 offs=0
0x12:pri[0] offs=0x1f82
block_row_dump:
tab 0, row 0, @0x1f82
tl: 22 fb: --H-FL-- lb: 0x1 cc: 3
col 0: [10] 61 62 63 20 20 20 20 20 20 20
col 1: [ 3] 31 32 33
col 2: [ 3] 2c 66 64
end_of_block_dump
End dump data blocks tsn: 5 file#: 5 minblk 32 maxblk 32


观察dump出来的结果,可以发现以下几点:


1.对于每个字段,除了保存字段的值以外,还会保存当前字段中数据的长度。而且,oracle显然没有把字段的长度定义或类型定义保存在block中,这些信息保存在oracle的数据字典里面。


2. 根据dump的结果,可以清楚的看到,字符类型在数据库中是以ascii格式存储的。


SQL> select chr(to_number('61', 'xx')) from dual;


CH
--
a


3.char类型为定长格式,存储的时候会在字符串后面填补空格,而varchar2和long类型都是变长的。


SQL> SELECT DUMP(CHAR_COL, 16) D_CHAR FROM TEST_CHAR;


D_CHAR
-------------------------------------------------------------
Typ=96 Len=10: 61,62,63,20,20,20,20,20,20,20


SQL> SELECT DUMP(VARCHAR_COL, 16) D_VARCHAR2 FROM TEST_CHAR;


D_VARCHAR2
-------------------------------------------------------------
Typ=1 Len=3: 31,32,33


SQL> SELECT DUMP(LONG_COL, 16) D_VARCHAR2 FROM TEST_CHAR;
SELECT DUMP(LONG_COL, 16) D_VARCHAR2 FROM TEST_CHAR
*
ERROR 位于第 1 行:
ORA-00997: 非法使用 LONG 数据类型


由于DUMP不支持LONG类型,因此我们使用了alter system dump block的方式,通过比较两种方式得到的结果,发现DUMP()函数不但方便,结果清晰,而且指出了进行DUMP的数据类型,在以后的例子中,除非必要的情况,否则都会采用DUMP()函数的方式进行说明。


下面看一下插入中文的情况,首先看一下数据库的字符集


SQL> select name, value$ from sys.props$ where name like '%CHARACTERSET%';


NAME VALUE$
------------------------------ ------------------------------
NLS_CHARACTERSET ZHS16GBK
NLS_NCHAR_CHARACTERSET AL16UTF16


SQL> insert into test_char values ('定长', '变长', null);


已创建 1 行。


SQL> SELECT DUMP(CHAR_COL, 16) D_CHAR FROM TEST_CHAR;


D_CHAR
----------------------------------------------------------------
Typ=96 Len=10: 61,62,63,20,20,20,20,20,20,20
Typ=96 Len=10: b6,a8,b3,a4,20,20,20,20,20,20


SQL> SELECT DUMP(VARCHAR_COL, 16) D_VARCHAR2 FROM TEST_CHAR;


D_VARCHAR2
----------------------------------------------------------------
Typ=1 Len=3: 31,32,33
Typ=1 Len=4: b1,e4,b3,a4


根据dump结果,可以清楚的看出,普通英文字符和标点用一个字节表示,而中文字符或中文标点需要两个字节来表示。


下面,对比一下nchar和nvarchar2与char、varchar2类型有什么不同。


SQL> create table test_nchar (nchar_col nchar(10), nvarchar_col nvarchar2(10));


表已创建。


SQL> insert into test_nchar values ('nchar定长', 'nvarchar变长');


已创建 1 行。


从这里已经可以看出一些不同了,如果按照刚才中文的计算方法,'nvarchar变长'的长度是8+2*2=12已经超过了数据类型定义的大小,可是为什么插入成功了?


还是dump一下看看结果吧。


SQL> select dump(nchar_col, 16) from test_nchar;


DUMP(NCHAR_COL,16)
--------------------------------------------------------------
Typ=96 Len=20: 0,6e,0,63,0,68,0,61,0,72,5b,9a,95,7f,0,20,0,20,0,20


SQL> select dump(nvarchar_col, 16) from test_nchar;


DUMP(NVARCHAR_COL,16)
--------------------------------------------------------------
Typ=1 Len=20: 0,6e,0,76,0,61,0,72,0,63,0,68,0,61,0,72,53,d8,95,7f


这下就明白了,虽然仍然是采用ascii码存储,但是nchar使用的AL16UTF16字符集,编码长度变为2个字节。这样中文使用两个字节,对于可以用一个字节就表示的英文字符,采用了高位补0的方式凑足2位,这样,对于采用AL16UTF16字符集的nchar类型,无论中文还是英文都用2位字符表示。因此'nvarchar变长'的长度是10,并没有超过数据类型的限制。
1 bit
1 byte = 8 bits , in C language , called character or CHAR
=> can break a byte into two groups , one is called nibble , nnnn nnnn => 2 nibble.
1 word = 2 bytes = 16 bits , in C language , called an Integer , unsign 0~65535
=> MySQL smallint(5)
1 long word = 2 words = 4 bytes = 32 bits , unsign 0 ~ 4,294,967,295
=> MySQL int(10)

2008年4月13日 星期日

Oracle Audit

一、何謂數據庫審計?
數據庫審計,就是對數據庫的活動做跟蹤記錄,主要包括數據庫連接,SQL語句執行,數據庫對象訪問這些方面的跟蹤記錄。

二、審記記錄的存儲方式
分為兩種:一種是存儲在操作系統文件中,一種是存儲在system表空間中的SYS.AUD$表中。

三、對數據庫性能影響的考慮
審計必然需要占用CPU,因此,需要綜合平衡審計需求與性能之間的平衡性問題,以確定出最好的審許策略。

四、審記結果中包含哪些信息
前面講到審許結果的存儲分數據庫存儲和文件存儲兩種方式。對於數據庫存儲的情況,SYS.AUD$表中包含以下信息:
· 操作系統用戶名
· 數據庫用戶名
· 連接會話標識
· 終端標識
· 被訪問的schema對象名
· 嘗試的操作
· 操作的完整代碼
· 日期和時間戳

若審計記錄存儲在外部操作文件中,則該文件可能包含以下信息:
· 操作系統產生的審計記錄
· 數據庫的審計記錄
· 被審計到的數據庫操作
· 超級管理員(SYS)的審計記錄
其中,被寫到文件中的審計記錄是以編碼的方式存儲的,如果要理解這些編碼所對應的信息,可以查詢以下數據字典表:
編碼信息 數據字典表
-------------------------------
數據庫操作代碼 表示嘗試的操作。它的相關描述可以從數據字典表AUDIT_ACTIONS表中查詢到
操作所使用的權限 可以在字典表SYSTEM_PRIVILEGE_MAP中查詢到對應的說明
完整的操作代碼 操作成功時將返回0,失敗時返回相關oracle錯誤信息,錯誤信息碼所對應的說明可以從oracle官方文檔中獲得
--------------------------------

五、缺省的審計
不論當前是否已經開啟的審計功能,數據庫都會把一些數據庫相關的操作寫入外部審計文件中(注意:不是寫入SYS.AUD$表),這些被缺省審計的操作是:
· 以超級管理員權限對數據庫的連接(connect AS SYSDBA或connect AS SYSOPER)
· 數據庫啟動
· 數據庫停止

六、對超級管理員用戶的操作行為的審計
超級管理員用戶指的是以AS SYSDBA 或 AS SYSOPER方式連接數據庫的用戶。初始化參數AUDIT_SYS_OPERATIONS用來指定是超級管理員的審計選項,如果將AUDIT_SYS_OPERATIONS設置為TRUE,那麼所有超級管理員的操作都將被審計,而不管當前是否有開啟審計功能,而且所有的審計信息都被寫入外部審計文件中(注意:不是寫入SYS.AUD$表)。

七、執行審計
1.設定審計記錄的存放位置
初始化參數AUDIT_TRAIL指定了審計記錄的存放位置,該參數有三個取值:
· DB 審計記錄存放在數據庫的SYS.AUD$表中
· OS 審計記錄存放在外部的操作系統文件中
· NONE 關閉審計(缺省值)
初始化參數AUDIT_FILE_DEST指定了當審外部審記文件目標存儲路徑,其缺省值是$ORACLE_HOME/rdbms/audit
2.審計選項
這個審計選項指的是執行審計的AUDIT語句的可選項。AUDIT語句的語法請參考oracle官方SQL參考。

3.以實例說明審計
a.審計某用戶的會話的創建與結束
AUDIT SESSION BY scott,fey;
b.審計所有用戶的會話的創建與結束
AUDIT SESSION;
c.審計刪除表的操作
AUDIT DELETE ANY TABLE;
c.審計刪除表的操作(限制:只審計刪除失敗的情況)
AUDIT DELETE ANY TABLE WHENEVER NOT SUCCESSFUL;
d.審計刪除表的操作(限制:只審計刪除成功的情況)
AUDIT DELETE ANY TABLE WHENEVER SUCCESSFUL;
e.審計刪除表的操作(限制:同一個會話中相同的操作語句只審計一次)
AUDIT DELETE ANY TABLE BY SESSION;
(注:對於這種情況,如果審計記錄被設定為存儲在外部文件中時,這個效果是體現不出來的,因為oracle無法判斷是否已經審計過相同的操作語句。)
f.審計刪除表的操作(限制:每支刪除語句都審計,不論同一會話中是否有多條相同的操作語句)
AUDIT DELETE ANY TABLE BY ACCESS;
g.審計對fey.employee表的delete操作
AUDIT DELETE ON fey.employee;
h.審計對fey.employee表的delete、updet、insert操作
AUDIT DELETE,UPDATE,INSERT ON fey.employee;

八、停止審計
停止審計使用NOAUDIT語句,該語句的語法請參考oracle官方SQL參考。下面以實例說明NOAUDIT的使用:
a.停止所有對會話的創建與結束的審計
NOAUDIT SESSION;
b.停止對用戶fey,scott的會話的創建與結束的審計
NOAUDIT SESSION BY fey,scott;
c.停止審計刪除表的操作
NOAUDIT DELETE ANY TABLE;
c.停止審計刪除表的操作(限制:停止審計刪除失敗的情況)
NOAUDIT DELETE ANY TABLE WHENEVER NOT SUCCESSFUL;
d.停止審計刪除表的操作(限制:停止審計刪除成功的情況)
NOAUDIT DELETE ANY TABLE WHENEVER SUCCESSFUL;
g.停止審計對fey.employee表的delete操作
NOAUDIT DELETE ON fey.employee;
h.停止審計對fey.employee表的delete、updet、insert操作
NOAUDIT DELETE,UPDATE,INSERT ON fey.employee;

九、對審計記錄表SYS.AUD$的管理
當SYS.AUD$表的審計記錄越來越多的時候,以至達到存儲極限時,會因為審計記錄無法寫入而產生錯誤。或許我還也需要對該表的數據進行一些轉儲或者碎片的整理,或是刪除一些我們認為不再需要的審計記錄。這些都是要考慮的事情。下面給出一個對該表進行存儲碎片的整理的一個方法:
a.將該表的數據select into到另一個表中,或利用export導出到外部文件
b.truncate這張表(要以超級管理員登錄才行)
c.再將原先轉儲的數據再加載進來。

也許我們需要對針對SYS.AUD$表的操作進行審計,如:AUDIT INSERT,UPDATE,DELETEON sys.aud$ BY ACCESS;

十、Fine-Grained審計
如前面所述,審計的記錄中並沒有含操作所作用的數據,比如說,需要審計針對一個表的select,而且需要在審計記錄中包含select語句所返回的數據。這時,就需要用到Fine-Grained審計。Fine-Grained審計是基於oracle的事件,其原理是在insert,update或 delete相關的事件中截取相關的數據。屬於orale程序開發的范疇。具體可以參考相關oracle文檔。

十一、審計相關的數據字典視圖
STMT_AUDIT_OPTION_MAP
AUDIT_ACTIONS
ALL_DEF_AUDIT_OPTS
DBA_STMT_AUDIT_OPTS
DBA_PRIV_AUDIT_OPTS
DBA_OBJ_AUDIT_OPTS
USER_OBJ_AUDIT_OPTS
DBA_AUDIT_TRAIL
USER_AUDIT_TRAIL
DBA_AUDIT_OBJECT
USER_AUDIT_OBJECT
DBA_AUDIT_SESSION
USER_AUDIT_SESSION
DBA_AUDIT_STATEMENT
USER_AUDIT_STATEMENT
DBA_AUDIT_EXISTS

DBA_AUDIT_POLICIES
DBA_FGA_AUDIT_TRAIL

各視圖的詳細說明請參考oracle官方參考手冊。

2008年3月28日 星期五

Table Last Update Time

Method1 : but no reliability
select ora_rowscn from table
select scn_to_timestamp(ora_rowscn) from table

Method2 : Audit to Monitor
One option is as follows:

(1) Turn the auditing on: AUDIT_TRAIL = true in init.ora

(2) Restart the instance if its running.

(3) Audit the table:

AUDIT INSERT,SELECT,DELETE,UPDATE on TableName
by ACCESS WHENEVER SUCCESSFUL
(4) Get the desired information using :

SELECT OBJ_NAME,ACTION_NAME ,to_char(timestamp,'dd/mm/yyyy , HH:MM:SS')
from sys.dba_audit_object.

2008年3月26日 星期三

SQL> create tablespace test1
2 datafile 'C:\oracle\product\10.1.0\oradata\orcl\test1.dbf' size 2M;

drop tablespace test1
SQL> create tablespace test1
2 datafile 'C:\oracle\product\10.1.0\oradata\orcl\test1.dbf' reuse;

drop tablespace test1
including contents and datafiles;

SQL*PLUS Command Regular Expression

SQL> select name,issys_modifiable from v$system_parameter where issys_modifiable
<>false;

c /false/'FALSE'/

run

2008年3月25日 星期二

Insert Into Statement

INSERT INTO "table_name" ("column1", "column2", ...)
VALUES ("value1", "value2", ...)

INSERT INTO "table1" ("column1", "column2", ...)
SELECT "column3", "column4", ...
FROM "table2"

Note that this is the simplest form. The entire statement can easily contain WHERE, GROUP BY, and HAVING clauses, as well as table joins and aliases.

ALTER TABLE

1.ALTER TABLE NAME
ALTER TABLE [PROJECT.]OLD_TABLE_NAME RENAME TO NEW_TABLE_NAME;
2.ALTER TABLE COLUMN NAME
ALTER TABLE [PROJECT.]TABLE_NAME RENAME COLUMN OLD_COLUMN_NAME TO NEW_COLUMN_NAME;
3.ALTER TABLE COLUMN DATA TYPE
ALTER TABLE [PROJECT.]TABLE_NAME MODIFY COLUMN_NAME NEW_DATATYPE;
4.ADD COLUMN
ALTER TABLE [PROJECT.]TABLE_NAME ADD COLUMN_NAME DATATYPE;
5.DROP COLUMN
ALTER TABLE [PROJECT.]TABLE_NAME DROP COLUMN COLUMN_NAME;

2008年3月23日 星期日

Oracle Install Attention

Built DB時,
密碼可不能設 XXX@XXX , 夾了 "@" 是建不起來的.
可能是 把 @後的 XXX 當成 SID ~ 有點鳥 試了一晚才發現.

2008年3月18日 星期二

Mysql Character Set 問題解決

轉載自
http://bluecat.csie.net/2007/12/17/2498/


老問題,不過一直懶得弄,都用懶人法先撐著。

懶人設定法,在 connect 後呼叫

SET NAMES ‘latin1′
如果要根本上治好,或是說連資料庫內的資料都正確的轉成 utf8 ,那就得作點苦工了。首先 MySQL 的 Character Set 變數有三

character_set_client client 傳給 server 使用的 charset ,即輸入
character_set_results server 傳給 client 使用的 charset ,即輸出
character_set_connection db 實際上存放時的 charset ,通常用 utf8

正常自動設定的話,character_set_connection 會是建立 db 時選擇的 charset,如果 table 或 field 有特別指定不同的 charset ,那麼就以指定的為準,不過這部份是 MySQL 自動轉換,所以不需要管,重點在於輸入與輸出的 charset 必須正確,才能正確的轉換。可以當成語言翻譯,首先必須指出自己使用的語言,伺服器就能正確的翻譯並紀錄成指定的語言,然後指出需要的語言,如此伺服器就能從紀錄翻譯出需要的語言。

懶人設定法就是不管是啥,一概都不轉碼,因為 SET NAMES ‘x’ 等同於

SET character_set_client = ‘x’
SET character_set_results =’x’
SET character_set_connection = ‘x’
也就是告訴資料庫設定傳進去的是 latin1 編碼,並且存成 latin1 編碼,跟存 raw byte data 很像,因此雖然 Database Charset 設成 UTF-8 ,但實際卻還是用 latin1 在處理資料;用 phpMyAdmin 的時,因為網頁編碼是 UTF-8,character_set_client & character_set_results 就會被設成 UTF-8,這時候,懶人設定法的資料就全部都會變亂碼, 因為 UTF-8 的編碼被當作 latin1 ,而這時又要求輸出 UTF-8,於是把原本就是 UTF-8 的資料又做了一次 latin1 -> UTF-8 轉換,會變亂碼也不奇怪了。如果是用 phpMyAdmin 插入資料,雖然 character_set_client 是 UTF-8 做了一次 UTF-8 -> latin1 轉換,但輸出時,因 character_set_results 也是 UTF-8,所以做了 latin1 -> UTF-8 的反轉換,因此得到原本的正常字串。

根本的 UTF-8 修正方式就是先用 latin1 編碼倒出資料,然後依據原始編碼轉碼成 UTF-8 後再倒回去,比較省事的方法是用 mysqldump 抓下來,然後用 vim 轉碼後在倒回去。

之前有個網頁是 Big5 ,就用 php 一筆筆拉出來,然後 mb_convert_encoding 成 UTF-8 ,再存回去,當然 Database 本身的 charset 已經設成 UTF-8 ,需要注意的是 field 的校對也要先設成 utf8_general_ci ,因為要順便作點處理,所以才用 php 做,不然用 mysqldump 應該比較快。

實例

資料庫是 UTF-8 編碼,可是資料都是 Big5 ,並用懶人設定寫入資料庫,現在要把資料庫內的資料從偽 UTF-8 轉成正確的資料以在 phpMyAdmin 中也正常顯示

connet 後,呼叫
mysql_query("SET NAMES utf8"); // 設定輸出為 utf8
mysql_query( "SET character_set_results = ‘latin1′"); // 但吐資料請給我 latin1 (即 Big5 的資料)
接著一筆筆拉出來,用 mb_convert_encoding 從 Big5 轉成 UTF-8 再存回去。

或是

connet 後,呼叫
mysql_query( "SET character_set_client = ‘big5′"); // 設定輸出為 big5
mysql_query( "SET character_set_results = ‘latin1′"); // 但吐資料請給我 latin1 (即 Big5 的資料)
mysql_query( "SET character_set_connection = ‘utf8′"); // 資料庫是 utf8
接著一筆筆拉出來,再直接存回去就好

2008年3月9日 星期日

Creating a Function-Based Index

You must set the initialization parameter QUERY_REWRITE_ENABLED to true in order to take advantage of function-based indexes.

show parameter QUERY_REWRITE_ENABLED;
if false then
SQL> ALTER SYSTEM SET QUERY_REWRITE_ENABLED=TRUE;

statement :

CREATE INDEX INDEX_Name
ON table(func(table.column));

ex.
CREATE INDEX QUEUE_TABLE_ID01
ON QUEUE_TABLE(MOD(NO,2));


Drop Index
DROP INDEX INDEX_NAME;

2008年3月6日 星期四

Login:
C:\oracle\ora92\network\ADMIN>sqlplus youraccount/yourpasswd@yourhostname

2008年3月4日 星期二

Perl DBI Calling Oracle Procedure

How does one invoke stored procedures with DBI?
There is currently no standard way to call stored procedures with DBI. However, if you have created a stored procedure within an Oracle database, you can use $dbh->do() to immediately execute the procedure:
$dbh->do("BEGIN myPackage.myProcedure; END;");

Or
Sample:
my $sth=$dbh_o->prepare("begin PRO_BID_QUEUE_TABLE(:in1,:int2,:T); end;");
$sth->bind_param("in1",20);
$sth->bind_param("in2",30);
my $result;
$sth->bind_param_inout("T",\$result,20);
$sth->execute();
$sth->commit();

CREATE OR REPLACE PROCEDURE
PRO_BID_QUEUE_TABLE( N1 IN NUMBER , N2 IN NUMBER , TOTAL OUT NUMBER)
IS
BEGIN
TOTAL := N1 + N2 ;
END;

2008年3月2日 星期日

Oracle -TableSpace( Create Table, Manage )

(轉載至網路)
TableSpace介紹


簡介
  TableSpace 是Oracle空間管理上的邏輯單位,實體上存放資料的是Tablespace裡面的檔案(Data File);而我們所熟悉的Table就放在這 一個一個的檔案裡面。所以TableSpace可以看成是Data File的群組。通常在管理上會把使用者的資料與Oracle系統的物件以不同的Tablespace做切分 。如果一個Oracle上有多個不同的AP系統,以不同的TableSpace做切割,則可以達到管理與備份的目的。但是TableSpace的功用也不僅僅只是簡單的群組分類而已,Oracle 提供了許多功能上的參數來設定TableSpace來達到空間管理與效能增進的目的。

  有必要提的是,TableSpace沒辦法跨資料庫,TableSpace中的Data File沒辦法跨TableSpace,Data File中的Table (Segement)可以跨 Data File,但不能跨TableSpace。簡單的來說,一個Table裡面的資料是有可能因為Oracle的空間分配而分布在同一個TableSpace的 不同的Data File中的;因此一個Data File創出來後,是不能隨便刪除的,這將會造成嚴重的資料損毀的問題。



SYSTEM與Non-SYSTEM TableSpace
  當資料庫剛建立起來,系統會建立一個叫做SYSTEM的系統TableSpace,存放SYS、SYSTEM等User重要的系統資料(ex:資料字典與預儲程序等) 如果我們建立Oracle User時,不指定預設的TableSpace,則此User則會以SYSTEM TableSpace作為預設的TableSpace。 這將造成管理上的混亂與嚴重的效能問題,這是必須特別注意的。



TableSpace的類型:Permanent、Undo、Temporary

Permanent Tablespace
  一般我們創建給AP使用的都是Permanent Tablespace。裡面物件的生命週期不會隨著交易或者 使用者的session結束而消失。



Undo Tablespace
  Undo Tablespace是系統用的特殊的Tablespace,用來取代過去的rollback segement的機制, 主要的功用是提供使用者修改資料未commit之前的read consistency的功能以及rollback交易的功能。 也因為undo tablespace主要是取代過去的rollback segement的機制,所以不能存放其他種類的segement。 undo tablespace只能是local managed。



Temporary Tablespace
  Temporary Tablespace也是系統用的特殊的Tablespace。當使用者需要做排序時, 有時就會使用Temporary Tablespace,因此裡面的Segement的生命週期都很短,可能交易結束或者 User的Session結束就會消失。每個系統都必須要有一個預設的Temporary Tablespace(Default Temporary Tablespace), 如果沒有的話,忘了指定使用哪個Temporary Tablespace的使用者會以SYSTEM tablespace來當作Temporary Tablespace,這樣就很糟糕。 以下列出幾個Temporary Tablespace的特性。


Temporary Tablespace是NOLOGGING模式,因此若資料庫損毀,做Recovery不需要恢復Temporary Tablespace。
Temporary最好是使用Local managed Tablespace
若使用local managed模式,UNIFORM SIZE參數最好是Sort_Area_Size的參數,這樣效能比較好。
Uniform size預設1024K,而Sort_area_size預設是512K
Temporary Tablespace不能使用local managed的AUTOALLOCATE參數。







TableSpace的Extent空間管理:Local Managed 與Dictionary Managed
  Local Managed 與Dictionary Managed最主要的分別,在於空間管理方式的不同。Local managed 的管理方式是讓 每個TableSpace自己利用bitmaps去管理他自己的空間,而Dictionary Managed則是利用SYSTEM TableSpace的資料字典來做空間管理。 這兩者最大的不同在於Local managed大大的改善了Oracle做空間管理(例如:產生新的Exten或釋放Extent...等)時,搶奪 SYSTEM TableSpace資源的問題。所以Oracle從8i以後已經朝Local managed的方向去走了,所以我們應該盡量使用Local managed的方式才對,所以Dictionary managed的方式不多做介紹了。

Local managed tablespace

Local managed使用bitmaps做空間管理。
bitmaps中每個bit代表一個data block或者一堆相鄰的data block(extent)
從10g開始,SYSTEM Tablespace預設使用local managed -->Oracle建議使用local managed的證據。
假如SYSTEM TableSpace是local managed,那麼其他TableSpace必須是local managed。
若沒指定使用local managed或者dictionary managed,則預設使用local managed。
使用local managed可以增進效能,因為減少了SYSTEM TableSpace的效能競爭。
使用local managed則不需要做空間縫合(loalescing),因為相鄰的不同大小的extent,辨識extent使用狀態的bits也在一起 ,Oracle可以直接使用這些相鄰的extent。不需要先進行縫合才可以使用。這也可以增進部份效能。




local managed的extent空間管理(Extent Management):AUTOALLOCATE與UNIFORM
  AUTOALLOCATE與UNIFORM這兩個參數,是用來設定Local managed的extent大小的參數。 AUTOALLOCATE是讓Oracle自己來決定extent的大小;而UNIFORM則是強制規定TableSpace中extent的為固定的大小。 通常若你明確的知道extent必須多大,才會使用UNIFORM,使用UNIFORM的好處是每個extent的大小都相同,不會產生空間破碎的問題。 但是如果無法預知extent必須多大,使用AUTOALLOCATE會比較好,讓Oracle自己決定使用extent的大小,可以比較符合實際的需求 ,因此會比較節省空間,但是這可能會產生部分空間破碎的問題。使用AUTOEXTENT,Oracle會使用的extent大小為64k、1M、8M、64M。 根據我系統上使用的結果,99.95%的extent都是使用64k、只有少部分使用1M 的extent,所以其實破碎的情況不嚴重,使用AUTOALLOCATE 在我的系統上其實就夠用了。想知道你的TableSpace所使用的Extent有幾種,請用下列的語法:

Select bytes,count(*) from dba_extents where tablespace_name='your_tablespace_name' group by bytes




Local managed中的Segment的空間管理(Segment Space Management ):AUTO與MANUAL
  Tablespace中的Segment的空間管理上,可以設置的參數為AUTO與MANUAL。MANUAL是使用 我們熟悉的PCTUSED、FREELISTS、FREELIST GROUPS的方式來管理Segment中的data block;而AUTO則是 使用bitmaps來管理data block。使用AUTO來管理的話,以往create tablespace或create table時設定的 storage的參數設定都不需要再設定了,因為data block的管理已經是bitmaps了,不再是free list了。如果沒有特別的需求話 ,使用AUTO會比使用MANUAL有更好的空間利用率,與效能上的提升。



Local managed中的Create TableSpace範例
Create Tablespace MYDATA
Datafile '/u1/oradata/mydb/mydata1.dbf' size 100M AUTOEXTEND ON NEXT 10M MAXSIZE UNLIMITED ,
'/u1/oradata/mydb/mydata2.dbf' size 100M AUTOEXTEND ON NEXT 10M MAXSIZE UNLIMITED
Extent Management Local
Segment Space Management Auto;



dictionary managed中的Create TableSpace範例
Create Tablespace MYDATA
Datafile '/u1/oradata/mydb/mydata1.dbf' size 100M AUTOEXTEND ON NEXT 10M MAXSIZE UNLIMITED
Extent Management Dictionary
Default Storage (
Initial 64k
next 64k
minextents 2
maxextents unlimited
pctincrease 0 );

2008年2月24日 星期日

Oracle Pagenation 換頁

Pagenation 換頁 :
SELECT * from (select n.*,rownum num from XX.TABLE1 n WHERE rownum <=100) where num >= 50;
//第50~100筆

Oracle Time Format (to_char,to_date)

select to_char(sysdate,'YYYY/MM/DD HH:MI:SS') FROM DUAL;

select count(column) from table t
where date >to_date('2007/09/01 01:01:01','YYYY/MM/DD HH24:MI:SS')