当前位置: 数据库>其它
本页文章导读:
▪深入理解Oracle表(6):堆组织表(HOT)和索引组织表(IOT)的区别 ㈠ HOT和IOT的起源 堆组织表的存储速度因为不用考虑排序, 所以存储速度会比较快. 但是要查找符合某个条件的记录,.........
▪Linux/Unix shell 自动导入Oracle数据库 使用shell脚本实现对Oracle数据库的监控与管理将大大简化DBA的工作负担,如常见的对实例的监控,监听的监控,告警日志的监控,以及数据库的备份,AWR report的自动邮.........
▪Oracle online redo log 扫盲 Oracle 的日志分为:ONLINE REDO LOG 和 archived log
online redo log:
一个数据库至少要有2组 redo log,每组 redo log 至少要有一个 member(出于安全考虑,建议每组 redo log 至少有 2 个多元化的 redo log member.........
[1]深入理解Oracle表(6):堆组织表(HOT)和索引组织表(IOT)的区别
来源: 互联网 发布时间: 2013-11-07
㈠ HOT和IOT的起源
堆组织表的存储速度因为不用考虑排序, 所以存储速度会比较快. 但是要查找符合某个条件的记录, 就必须得读取全部的记录以便筛选.
而这个时候为了加快查询速度, 索引就出现了, 索引是针对少量特定字段的值拿出来进行排序存储, 并记录在表中的位置,
而因为索引是有序的, 所以就会很容易通过索引查询到具体的记录位置, 然后再根据记录位置直接从表中读取该记录.
同时因为索引的字段较少, 所以索引通常会比其基表小得多.
从上面通过索引访问表记录的方式可以看出, 当要访问的数据量较大时, 通过每一条记录的位置去访问原始记录,
每一条符合条件的记录都需要经过索引访问后再访问基表这样一个复杂的过程, 这会花费很多时间,
同样, 如果不经过索引而直接查询表, 也可能因为表字段太多, 记录较大的情况下把全部的数据读取进来, 这也会花费很多时间.
那怎么办呢?
这个时候就会想到, 如果表中数据本身就是有序的, 这样查询表的时候就可以快速的找到符合条件的记录位置,
而很容易判断符合条件记录的位置, 这样只需要读取一小部分数据出来就可以了, 不需要全表记录都读取出来进行判断.
索引表就这样产生了.当然索引表中插入,更新资料的时候可能会因为需要排序而将数据重组, 这时候数据插入或更新速度会比堆组织表慢一些.
如果堆组织表上有索引, 那么对堆组织表的插入也会因为要修改索引而变慢
我们可以看到堆组织表+索引的方式 与 索引表 都能够实现数据的快速查找, 那为什么不全部采用索引表呢, 这样不是很简单吗?
我能想到的是前者我们可以针对不同的查找条件建立多个索引, 而后者却不行, 后者只能对某一组查询条件有效.
当然了,索引表上查询任何记录都是走索引的, 因为它本身就是索引结构.
当查询条件不符合指定条件时, 必须走 index full sacn , 需要扫描全部索引.
这就是说这时无法利用索引表已经根据某些字段排序的事实.也即排序对于这个查询来说无用.
而符合指定的条件时就会走 index range scan
㈡ 定义
① 堆组织表,其索引中记录了记录所在位置的rowid,查找的时候先找索引,然后再根据索引rowid找到块中的行数据。索引和表数据是分离的
② 索引组织表,其行数据以索引形式存放,因此找到索引,就等于找到了行数据。索引和数据是在一起的
㈢ 查找过程
① 堆组织表
一般索引大概3-5层,比如rowid为007,那么要找到007可能会先从第一层找<1000,再在第二层找到<100
然后在第三层找到007(注意这已经是3次I/O)
接着再通过007中标识的rowid去对应的磁盘上读取块中的行数据(第4次I/O)
② 索引组织表
前面的步骤同上,但是找到007后,由于数据和索引在一起,因此不必再找什么rowid,直接返回结果了
堆组织表的存储速度因为不用考虑排序, 所以存储速度会比较快. 但是要查找符合某个条件的记录, 就必须得读取全部的记录以便筛选.
而这个时候为了加快查询速度, 索引就出现了, 索引是针对少量特定字段的值拿出来进行排序存储, 并记录在表中的位置,
而因为索引是有序的, 所以就会很容易通过索引查询到具体的记录位置, 然后再根据记录位置直接从表中读取该记录.
同时因为索引的字段较少, 所以索引通常会比其基表小得多.
从上面通过索引访问表记录的方式可以看出, 当要访问的数据量较大时, 通过每一条记录的位置去访问原始记录,
每一条符合条件的记录都需要经过索引访问后再访问基表这样一个复杂的过程, 这会花费很多时间,
同样, 如果不经过索引而直接查询表, 也可能因为表字段太多, 记录较大的情况下把全部的数据读取进来, 这也会花费很多时间.
那怎么办呢?
这个时候就会想到, 如果表中数据本身就是有序的, 这样查询表的时候就可以快速的找到符合条件的记录位置,
而很容易判断符合条件记录的位置, 这样只需要读取一小部分数据出来就可以了, 不需要全表记录都读取出来进行判断.
索引表就这样产生了.当然索引表中插入,更新资料的时候可能会因为需要排序而将数据重组, 这时候数据插入或更新速度会比堆组织表慢一些.
如果堆组织表上有索引, 那么对堆组织表的插入也会因为要修改索引而变慢
我们可以看到堆组织表+索引的方式 与 索引表 都能够实现数据的快速查找, 那为什么不全部采用索引表呢, 这样不是很简单吗?
我能想到的是前者我们可以针对不同的查找条件建立多个索引, 而后者却不行, 后者只能对某一组查询条件有效.
当然了,索引表上查询任何记录都是走索引的, 因为它本身就是索引结构.
当查询条件不符合指定条件时, 必须走 index full sacn , 需要扫描全部索引.
这就是说这时无法利用索引表已经根据某些字段排序的事实.也即排序对于这个查询来说无用.
而符合指定的条件时就会走 index range scan
㈡ 定义
① 堆组织表,其索引中记录了记录所在位置的rowid,查找的时候先找索引,然后再根据索引rowid找到块中的行数据。索引和表数据是分离的
② 索引组织表,其行数据以索引形式存放,因此找到索引,就等于找到了行数据。索引和数据是在一起的
㈢ 查找过程
① 堆组织表
一般索引大概3-5层,比如rowid为007,那么要找到007可能会先从第一层找<1000,再在第二层找到<100
然后在第三层找到007(注意这已经是3次I/O)
接着再通过007中标识的rowid去对应的磁盘上读取块中的行数据(第4次I/O)
② 索引组织表
前面的步骤同上,但是找到007后,由于数据和索引在一起,因此不必再找什么rowid,直接返回结果了
作者:linwaterbin 发表于2013-2-8 13:17:28 原文链接
阅读:0 评论:0 查看评论
[2]Linux/Unix shell 自动导入Oracle数据库
来源: 互联网 发布时间: 2013-11-07
使用shell脚本实现对Oracle数据库的监控与管理将大大简化DBA的工作负担,如常见的对实例的监控,监听的监控,告警日志的监控,以及数据库的备份,AWR report的自动邮件等。本文给出Linux 下使用 shell 脚本来实现自动导入Oracle数据库。
Linux Shell以及导入导出的相关参考:
Linux/Unix shell 脚本中调用SQL,RMAN脚本
Linux/Unix shell sql 之间传递变量
Linux/Unix shell 调用 PL/SQL
Linux/Unix shell 监控Oracle实例(monitor instance)
Linux/Unix shell 监控Oracle监听器(monitor listener)
Linux/Unix shell 监控Oracle告警日志(monitor alter log file)
数据泵 EXPDP 导出工具的使用
数据泵IMPDP 导入工具的使用
导入导出 Oracle 分区表数据
expdp impdp中 exclude/include 的使用
使用 Oracle Datapump API 实现数据导出
1、Linux/Unix shell 自动导入Oracle数据库脚本
# +------------------------------------------------+ # | Import database by schema | # | file_name: impdp.sh | # | Parameter: Oracle_SID | # | Usage: | # | ./impdb.sh ${ORACLE_SID} | # | Author : Robinson | # | Blog : http://blog.csdn.net/robinson_0612 | # +------------------------------------------------+ # #!/bin/bash # -------------------- # Define variable # -------------------- if [ -f ~/.bash_profile ]; then . ~/.bash_profile fi # -------------------------- # Check SID # -------------------------- if [ -z "${1}" ];then echo "Usage: " echo " `basename $0` ORACLE_SID" exit 1 fi ORACLE_SID=$1; export ORACLE_SID DT=`date +%Y%m%d`; export DT SRC_ORA_SID=SY5221A export SRC_ORA_SID TIMESTAMP=`date +%Y%m%d_%H%M` LOG_DIR=/u02/database/${ORACLE_SID}/BNR/dump LOG_FILE=$LOG_DIR/impdb_${ORACLE_SID}_${TIMESTAMP}.log DUMP_DIR=/u02/database/${ORACLE_SID}/BNR/dump TAR_FILE=EXP_${SRC_ORA_SID}_${DT}.tar.gz DUMP_FILE=EXP_${SRC_ORA_SID}_${DT}.dmp DUMP_LOG=IMP_${ORACLE_SID}_${DT}.log LAST_EXP_DUMP_LOG=${DUMP_DIR}/EXP_${SRC_ORA_SID}_${DT}.log RETENTION=1 # ------------------------------------------------------------------------ # Check the target database status, if not available send mail and exit # ------------------------------------------------------------------------ db_stat=`ps -ef | grep pmon_$ORACLE_SID | grep -v grep| cut -f3 -d_` if [ -z "${db_stat}" ]; then MAIL_SUB=" $ORACLE_SID is not available on `hostname` before try to import data !!!" # $MAIL_DIR/sendEmail -u $MAIL_SUB -f $MAIL_FM -t $MAIL_LIST -m $MAIL_SUB echo ${MAIL_SUB} |mail -s " $ORACLE_SID is not available on `hostname` !!!" dba@trade.com exit 1 fi # --------------------------------------------------- # Unzip the dump file # --------------------------------------------------- if [ -s "${DUMP_DIR}/$TAR_FILE" ] ; then cd ${DUMP_DIR} tar -xvf ${TAR_FILE} else MAIL_SUB="No dumpfile was found for ${ORACLE_SID} before import." echo "No dumpfile was found for ${ORACLE_SID} before import."|mail -s $MAIL_SUB dba@trade.com exit 1 fi # ----------------------------------------------------------------------------- # Check dumpfile and export log file are correct, if no send mail and exit # ----------------------------------------------------------------------------- date >${LOG_FILE} echo "The hostname is :`hostname`">>$LOG_FILE echo "The source database is :${SRC_ORA_SID}" >>${LOG_FILE} echo "The target database is :${ORACLE_SID}">>$LOG_FILE echo " " >>${LOG_FILE} flag=`cat ${LAST_EXP_DUMP_LOG} | grep -i "successfully completed"` if [ -n "${flag}" ] && [ -s "${DUMP_DIR}/${DUMP_FILE}" ] ; then echo -e "The dumpfile exists and can be imported to ${ORACLE_SID} \n">>${LOG_FILE} else echo "The dumpfile does not exist or exist with errors on `hostname` before try to import data !!!" >>${LOG_FILE} mail -s "The dumpfile does not exists or exist with errors for ${ORACLE_SID}" dba@trade.com <${LOG_FILE} exit 1 fi # ------------------------------------------------------------------------------------------ # Remove all objects for specific schema before import data, if error send mail and exit # ------------------------------------------------------------------------------------------ echo -e "Prepare plsql script to remove all objects for specific schema....\n" >>$LOG_FILE echo " DECLARE VERIFICATION VARCHAR2(200); BEGIN VERIFICATION := 'BO_ADMIN'; BO_ADMIN.GO_UTIL_DROP_SCHEMA_OBJECTS ( VERIFICATION ); COMMIT; END; / exit ">/tmp/remove_obj.sql if [ -s /tmp/remove_obj.sql ]; then echo -e "Running pl/sql script to remove objects for specific schema... \n" >>${LOG_FILE} $ORACLE_HOME/bin/sqlplus -s "/ as sysdba" @/tmp/remove_obj.sql >/tmp/remove_obj_result.log else echo -e "No any plsql script found to remvoe objects. please remove them before import..." >>$LOG_FILE MAIL_SUB="Import data to ${ORACLE_SID} error. Please remove objects for specific schema firstly" mail -s $MAIL_SUB dba@trade.com <${LOG_FILE} exit 1 fi res=`cat /tmp/remove_obj_result.log | grep ORA- | grep -v grep` if [ -n "${res}" ] ; then echo -e "Some errors caught during remove object, ingore them. \n" >>${LOG_FILE} fi rm /tmp/remove_obj.sql >/dev/null # ---------------------------------------------------------- # Start import data to target database # ---------------------------------------------------------- echo -e "Starting import data to target database ...\n" >>${LOG_FILE} impdp \'\/ as sysdba \' directory=db_dump_dir dumpfile=${DUMP_FILE} logfile=${DUMP_LOG} schemas=BO_ADMIN \ table_exists_action=replace #parallel=3 RC=$? cat ${DUMP_DIR}/${DUMP_LOG}>>$LOG_FILE if [ "${RC}" -ne 0 ]; then echo -e " Some errors caught during import data. exit !!!! \n" >>$LOG_FILE MAIL_SUB="Import data to ${ORACLE_SID} errors, exit, please check !!!" mail -s $MAIL_SUB dba@trade.com <${LOG_FILE} exit 1 fi # ---------------------------------------------------------- # Compile invalid objects # ---------------------------------------------------------- echo "">>${LOG_FILE} echo -e "Starting compile invalid objects ....\n" >>$LOG_FILE echo " SET LINESIZE 145 SET PAGESIZE 9999 clear columns clear breaks clear computes column owner format a25 heading 'Owner' column object_name format a30 heading 'Object Name' column object_type format a20 heading 'Object Type' column status format a10 heading 'Status' column object_name format a30 heading 'Object Name' column object_type format a20 heading 'Object Type' column status format a10 heading 'Status' break on owner skip 2 on report compute count label '' of object_name on owner compute count label 'Grand Total: ' of object_name on report spool /tmp/invalid_obj.log SELECT owner , object_name , object_type , status FROM dba_objects WHERE status <> 'VALID' ORDER BY owner, object_name / spool off; exit ">/tmp/list_invalid_obj.sql sqlplus -silent "/ as sysdba" <<EOF @$ORACLE_HOME/rdbms/admin/utlrp.sql @/tmp/list_invalid_obj.sql EOF echo -e "List all invalid objects \n" >>${LOG_FILE} echo "------------------------------------------------------------">>${LOG_FILE} cat /tmp/invalid_obj.log >>$LOG_FILE flag=`cat ${DUMP_DIR}/${DUMP_LOG} | grep "completed with [0-9][0-9] error"` if [ -z "${flag}" ] ; then echo -e "Import data to ${ORACLE_SID} completed successful at `date` ...\n" >>${LOG_FILE} echo "--------------------------- End of the log file ---------------------------">>${LOG_FILE} MAIL_SUB="Import data to ${ORACLE_SID} completed succ
[3]Oracle online redo log 扫盲
来源: 互联网 发布时间: 2013-11-07
Oracle 的日志分为:ONLINE REDO LOG 和 archived log
online redo log:
一个数据库至少要有2组 redo log,每组 redo log 至少要有一个 member(出于安全考虑,建议每组 redo log 至少有 2 个多元化的 redo log member)
redo log 循环使用,当一组日志写满后,就会切换到下一组日志。在非归档模式下,当所有日志组写满后,就会覆写之前写满且状态为 inactive 的日志组,以达到循环使用的目的。
在归档模式下,当所有日志组写满后,LGWR 要等到所有日志都已归档,且日志中记录的事务数据全部写入磁盘(inactive)后才会覆写之前的日志组,否则会一直等待这些任务完成。
日志内容:
redo log 的 redo entry 由一组变更向量组成。
变更向量(change vector):数据本身的改变、对应的 undo 改变、undo segment 的改变
示例:要修改某张表中的某个字段的值,那么修改之前的字段值就会放在 undo 中,为了申请该事务,还需要修改 undo segment 段头中事务表的信息,这个过程的描述就是
redo log 的变更向量。
变更向量的信息包括:版本号、事务操作代码、发生变更的数据块地址。在建立变更向量时,会从数据块中复制版本号。在恢复期间,Oracle 会读取向量并将修改应用于对应的数据块。
同时对数据块的版本号加 1.
Redo Thread 日志线程
单实例:一个 redo thread
RAC:实例数和redo thread 数量 1:1,每个实例都有自己的 thread
引入 redo thread 就是为了避免多个实例之间共享 redo log file 而导致争用,从而提高数据库性能。
一般而言,thread number=instance number
在 RAC 环境下,添加日志要指定线程:
ALTER DATABASE ADD LOGFILE THREAD 1 GROUP 5
('+DATA1/oradata/redo06.log','+DATA1/oradata/redo06.log') size 10m;
ALTER DATABASE ADD LOGFILE MEMBER
'...........' TO GROUP 5;
每个 REDO THREAD 或者(instance)至少需要两组日志,这些日志循环使用。当一组日志写满后,会发生 log switch 事件而使用下一组日志。如果数据库处于归档模式,
该归档日志还要被归档。在LOG SWITCH 时,会触发增量 checkpoint,启动 DBWR 后台进程将该日志中记录的所有操作所涉及的 dirty block 从 data buffer 写入磁盘文件。
一旦checkpoint 完成,这个日志组便可以被覆写重用。
online redo log:
一个数据库至少要有2组 redo log,每组 redo log 至少要有一个 member(出于安全考虑,建议每组 redo log 至少有 2 个多元化的 redo log member)
redo log 循环使用,当一组日志写满后,就会切换到下一组日志。在非归档模式下,当所有日志组写满后,就会覆写之前写满且状态为 inactive 的日志组,以达到循环使用的目的。
在归档模式下,当所有日志组写满后,LGWR 要等到所有日志都已归档,且日志中记录的事务数据全部写入磁盘(inactive)后才会覆写之前的日志组,否则会一直等待这些任务完成。
日志内容:
redo log 的 redo entry 由一组变更向量组成。
变更向量(change vector):数据本身的改变、对应的 undo 改变、undo segment 的改变
示例:要修改某张表中的某个字段的值,那么修改之前的字段值就会放在 undo 中,为了申请该事务,还需要修改 undo segment 段头中事务表的信息,这个过程的描述就是
redo log 的变更向量。
变更向量的信息包括:版本号、事务操作代码、发生变更的数据块地址。在建立变更向量时,会从数据块中复制版本号。在恢复期间,Oracle 会读取向量并将修改应用于对应的数据块。
同时对数据块的版本号加 1.
Redo Thread 日志线程
单实例:一个 redo thread
RAC:实例数和redo thread 数量 1:1,每个实例都有自己的 thread
引入 redo thread 就是为了避免多个实例之间共享 redo log file 而导致争用,从而提高数据库性能。
一般而言,thread number=instance number
在 RAC 环境下,添加日志要指定线程:
ALTER DATABASE ADD LOGFILE THREAD 1 GROUP 5
('+DATA1/oradata/redo06.log','+DATA1/oradata/redo06.log') size 10m;
ALTER DATABASE ADD LOGFILE MEMBER
'...........' TO GROUP 5;
每个 REDO THREAD 或者(instance)至少需要两组日志,这些日志循环使用。当一组日志写满后,会发生 log switch 事件而使用下一组日志。如果数据库处于归档模式,
该归档日志还要被归档。在LOG SWITCH 时,会触发增量 checkpoint,启动 DBWR 后台进程将该日志中记录的所有操作所涉及的 dirty block 从 data buffer 写入磁盘文件。
一旦checkpoint 完成,这个日志组便可以被覆写重用。
作者:xiangsir 发表于2013-2-8 18:22:24 原文链接
阅读:0 评论:0 查看评论
最新技术文章: