随笔-314  评论-209  文章-0  trackbacks-0
 

这段代码同样是执行了1000条insert语句,但是每一条语句都是不同的,因此ORACLE会把每条语句硬解析一次,其效率就比前面那段就低得多了。如果要提高效率,不妨使用绑定变量将循环中的语句改为

      sqlstr:='insert into 测试表 (:i,:i+1,:i*1,:i*2,:i-1) ';

      execute immediate sqlstr using i,i,i,i,i;

这样执行的效率就高得多了。

我曾试着使用绑定变量来代替表名、过程名、字段名等,结果是语句错误,结论就是绑定变量不能当作嵌入的字符串来使用,只能当作语句中的变量来用。

从效率来看,由于oracle10G放弃了RBO,全面引入CBO,因此,在10G中使用绑定变量效率的提升比9i中更为明显。

最后,前面说到绑定变量是在通常情况下能提升效率,那哪些是不通常的情况呢?

答案是:在字段(包括字段集)建有索引,且字段(集)的集的势非常大(也就是有个值在字段中出现的比例特别的大)的情况下,使用绑定变量可能会导致查询计划错误,因而会使查询效率非常低。这种情况最好不要使用绑定变量。

 

 

 

 

 

 

 

EXECUTE IMMEDIATE代替了以前Oracle8i中DBMS_SQL package包.它解析并马上执行动态的SQL语句或非运行时创建的PL/SQL块.动态创建和执行SQL语句性能超前,EXECUTE IMMEDIATE的目标在于减小企业费用并获得较高的性能,较之以前它相当容易编码.尽管DBMS_SQL仍然可用,但是推荐使用EXECUTE IMMEDIATE,因为它获的收益在包之上。

使用技巧

 

1. EXECUTE IMMEDIATE将不会提交一个DML事务执行,应该显式提交
如果通过EXECUTE IMMEDIATE处理DML命令,那么在完成以前需要显式提交或者作为EXECUTE IMMEDIATE自己的一部分. 如果通过EXECUTE IMMEDIATE处理DDL命令,它提交所有以前改变的数据

 

2. 不支持返回多行的查询,这种交互将用临时表来存储记录(参照例子如下)或者用REF cursors.

 

3. 当执行SQL语句时,不要用分号,当执行PL/SQL块时,在其尾部用分号.

 

4. 在Oracle手册中,未详细覆盖这些功能。下面的例子展示了所有用到Execute immediate的可能方面.希望能给你带来方便.

 

5. 对于Forms开发者,当在PL/SQL 8.0.6.3.版本中,Forms 6i不能使用此功能.

 

EXECUTE IMMEDIATE用法例子

 

1. 在PL/SQL运行DDL语句


begin
execute immediate 'set role all';
end;

 

2. 给动态语句传值(USING 子句)


declare
l_depnam varchar2(20) := 'testing';
l_loc    varchar2(10) := 'Dubai';
begin
execute immediate 'insert into dept values (:1, :2, :3)'
    using 50, l_depnam, l_loc;
commit;
end;

 

3. 从动态语句检索值(INTO子句)


declare
l_cnt    varchar2(20);
begin
execute immediate 'select count(1) from emp'
    into l_cnt;
dbms_output.put_line(l_cnt);
end;

 

4. 动态调用例程.例程中用到的绑定变量参数必须指定参数类型.黓认为IN类型,其它类型必须显式指定

 

declare
l_routin   varchar2(100) := 'gen2161.get_rowcnt';
l_tblnam   varchar2(20) := 'emp';
l_cnt      number;
l_status   varchar2(200);
begin
execute immediate 'begin ' || l_routin || '(:2, :3, :4); end;'
    using in l_tblnam, out l_cnt, in out l_status;

if l_status != 'OK' then
     dbms_output.put_line('error');
end if;
end;

 

5. 将返回值传递到PL/SQL记录类型;同样也可用%rowtype变量


declare
type empdtlrec is record (empno number(4),
                           ename varchar2(20),
                           deptno number(2));
empdtl empdtlrec;
begin
execute immediate 'select empno, ename, deptno ' ||
                   'from emp where empno = 7934'
    into empdtl;
end;

 

6. 传递并检索值.INTO子句用在USING子句前

 

declare
l_dept    pls_integer := 20;
l_nam     varchar2(20);
l_loc     varchar2(20);
begin
execute immediate 'select dname, loc from dept where deptno = :1'
    into l_nam, l_loc
    using l_dept ;
end;

 

7. 多行查询选项.对此选项用insert语句填充临时表,用临时表进行进一步的处理,也可以用REF cursors纠正此缺憾.

declare
l_sal   pls_integer := 2000;
begin
execute immediate 'insert into temp(empno, ename) ' ||
                   '          select empno, ename from emp ' ||
                   '          where sal > :1'
    using l_sal;
commit;
end;

 

       对于处理动态语句,EXECUTE IMMEDIATE比以前可能用到的更容易并且更高效.当意图执行动态语句时,适当地处理异常更加重要.应该关注于捕获所有可能的异常.

posted @ 2010-11-01 14:42 xzc 阅读(951) | 评论 (0)编辑 收藏
insert append需要注意的
2010-07-28 11:34

1. append方式添加记录对insert into ... values语句不起作用。

2. 以append方式批量插入的记录,其存储位置在hwm 之上,即使hwm之下存在空闲块也不能使用。

3. 以append方式插入记录后,要执行commit,才能对表进行查询。否则会出现错误:

ORA-12838: 无法在并行模式下修改之后读/修改对象

4. 在归档模式下,要把表设置为nologging,然后以append方式批量添加记录,才会显著减少redo数量。在非归档模式下,不必设置表的nologging属性,即可减少redo数量。如果表上有索引,则append方式批量添加记录,不会减少索引上产生的redo数量,索引上的redo数量可能比表的redo数量还要大。

用insert append可以实现直接路径加载,速度比常规加载方式快。但有一点需要注意: insert append时在表上加“6”类型的锁,会阻塞表上的所有DML语句。因此在有业务运行的情况下要慎重使用。若同时执行多个insert append对同一个表并行加载数据,并不一定会提高速度。因为每一时刻只能有一个进程在加载(排它锁造成)。

SQL> create table test as select * from dba_objects where 1=2;

表已创建。

SQL> insert into test select * from dba_objects;

已创建11344行。

SQL> set lines 150
SQL> col object_type for a10
SQL> col object for a30
SQL> col username for a10
SQL> col osuser for a10
SQL> col program for a30
SQL> col sid for 99,999
SQL> col locked_mode for 99
SQL> col spid for 999,999
SQL> select o.object_type,o.owner||'.'||o.object_name object,s.sid,s.serial#,p.spid,s.username,s.osuser,s.program,l.lock
ed_mode
2 from v$locked_object l,dba_objects o,v$session s,v$process p
3 where l.object_id = o.object_id
4 and s.sid=l.session_id
5 and s.paddr=p.addr
6 and o.object_name = upper('&obj');
输入 obj 的值: test
原值    6: and o.object_name = upper('&obj')
新值    6: and o.object_name = upper('test')

OBJECT_TYP OBJECT                             SID    SERIAL# SPID         USERNAME   OSUSER     PROGRAM
       LOCKED_MODE
---------- ------------------------------ ------- ---------- ------------ ---------- ---------- ------------------------
------ -----------
TABLE      SYS.TEST                           147         19 784          SYS        CNPEKALT02 sqlplus.exe
                 3
                                                                                     2\jyu
可以看到,insert 时在表上加的是“3”类型的锁。

SQL> rollback;

回退已完成。

SQL> insert /*+ append */ into test select * from dba_objects;

已创建11344行。

SQL> set lines 150
SQL> col object_type for a10
SQL> col object for a30
SQL> col username for a10
SQL> col osuser for a10
SQL> col program for a30
SQL> col sid for 99,999
SQL> col locked_mode for 99
SQL> col spid for 999,999
SQL> select o.object_type,o.owner||'.'||o.object_name object,s.sid,s.serial#,p.spid,s.username,s.osuser,s.program,l.lock
ed_mode
2 from v$locked_object l,dba_objects o,v$session s,v$process p
3 where l.object_id = o.object_id
4 and s.sid=l.session_id
5 and s.paddr=p.addr
6 and o.object_name = upper('&obj');
输入 obj 的值: test
原值    6: and o.object_name = upper('&obj')
新值    6: and o.object_name = upper('test')

OBJECT_TYP OBJECT                             SID    SERIAL# SPID         USERNAME   OSUSER     PROGRAM
       LOCKED_MODE
---------- ------------------------------ ------- ---------- ------------ ---------- ---------- ------------------------
------ -----------
TABLE      SYS.TEST                           147         19 784          SYS        CNPEKALT02 sqlplus.exe
                 6
                                                                                     2\jyu

而执行insert append时在表上加的是“6”类型的锁。

insert append与一般的insert在表上加的锁不一样。insert append加的是exclusive的锁。因此要注意在执行insert append尽快提交,否则会阻塞其它事务对同一张表的DML语句。
此外, ORA-12838:是由于在执行insert append之后没有提交或回滚,接着又执行DML语句造成的。解决办法是在insert append 之后加上commit或rollback。
请看下面的测试:
SQL> delete from test;
已删除9831行。
SQL> insert /*+ append */ into test select * from temp_fsum_od;
已创建3277行。
SQL> insert into test select * from temp_fsum_od;
insert into test select * from temp_fsum_od
            *
第 1 行出现错误:
ORA-12838: 无法在并行模式下修改之后读/修改对象

SQL> update test set OD_CODE=upper(OD_CODE) ;
update test set OD_CODE=upper(OD_CODE)
       *
第 1 行出现错误:
ORA-12838: 无法在并行模式下修改之后读/修改对象

SQL> delete from test;
delete from test
*
第 1 行出现错误:
ORA-12838: 无法在并行模式下修改之后读/修改对象

SQL>
SQL> insert /*+ append */ into test select * from temp_fsum_od;
insert /*+ append */ into test select * from temp_fsum_od
*
第 1 行出现错误:
ORA-12838: 无法在并行模式下修改之后读/修改对象
注意,我先执行了一个delete语句,又执行了insert append. 这个delete语句并没有造成后面的insert append报错。
但在我执行了一个insert append之后,再执行任何DML语句都会报错。
这说明,在执行了insert append 之后,必须commit或rollback,才能再执行其它DML语句。
但在insert append之前可以执行DML语句,而不会对insert append造成影响。
所以我们注意一点就可以了,即只要业务允许,在执行insert

 

insert append方法的使用

大家众所周知,向数据库里插入数据有很多种方法,insert、sqlloader、for update等。每种方法都有其不同的特点。
但是每一种方法在其服务器设置不同的情况下也是有不同的执行情况的。例如:insert。
insert 属于DML语言(即数据操作语言,还包括select,delete,update)。网上介绍过一种insert append方法,语句格式为 insert /* +append+ */ into table_name select column_name1…… from table_name2 ; 这种方法据说可以占用很少的redo表空间,占用很少的redo表空间也就是省略了一些归档的时间,这样是可以提高insert的执行效率的!但是经过测试我发现insert append并不是在任何时候都可以节省时间的。
第一种情况:database为archivelog状态,这种情况下,就算你用insert append也是不一定提高插入效率的。但是如果你在建表的时候,将目标表建成nologging的,然后再使用insert append就会很快。
第二种情况:database为noarchivelog状态,这种情况下,如果情况下采用insert方法向表中插入数据,占用的redo空间的大小与archivelog状态下占用的大小是相当的,不论表是否为nologging。但是如果采用insert append方法的话,通过redo的占用值大家可以发现,不论表是否为nologging,所占用的redo的大小都是很小的。也就说明:在数据库为noarchivelog的状态下,采用insert append方法,如果表不是nologging,系统也会自动将表转换为nologging(即在执行insert append之前,先执行一个alter table arch1 nologging;)。
以下为测试的具体过程:
-------- 数据库为归档模式
create table arch (status varchar(2)) nologging;        ----- create a nologging table
Table created
create table arch1 (status varchar(2)) ;                   ----- create a logging table
Table created

select a.name, b.value
from v$statname a, v$mystat b
where a.statistic# = b.statistic#
and a.name = 'redo size'
and b.value > 0;                                                 ----- view redo engross space
NAME                                                                  VALUE
---------------------------------------------------------------- ----------
redo size                                                           1332780

insert into arch select 'ok' from dba_objects
29514 rows inserted
---- view redo engross space
NAME                                                                  VALUE
---------------------------------------------------------------- ----------
redo size                                                           1744516   ----- +411736

insert into arch1 select 'ok' from dba_objects
29514 rows inserted
---- view redo engross space
NAME                                                                  VALUE
---------------------------------------------------------------- ----------
redo size                                                           2156000   ------ +411484

insert /*+append*/ into arch select 'ok' from dba_objects
29514 rows inserted
---- view redo engross space
NAME                                                                  VALUE
---------------------------------------------------------------- ----------
redo size                                                           2169864   ----- +13864
insert /*+append*/ into arch1 select 'ok' from dba_objects
29514 rows inserted
---- view redo engross space
NAME                                                                  VALUE
---------------------------------------------------------------- ----------
redo size                                                           2555448   ----- +385584
spool off;
-------- 数据库为非归档模式
create table arch (status varchar(2)) nologging;                   ----- create a nologging table
Table created
create table arch1 (status varchar(2)) ;                             ----- create a logging table
Table created
---- view redo engross space                             
NAME                                                                  VALUE
---------------------------------------------------------------- ----------
redo size                                                             33208
insert into arch select 'ok' from dba_objects
29514 rows inserted
---- view redo engross space
NAME                                                                  VALUE
---------------------------------------------------------------- ----------
redo size                                                            444704 ----- +411496

insert into arch1 select 'ok' from dba_objects
29514 rows inserted
---- view redo engross space
NAME                                                                  VALUE
---------------------------------------------------------------- ----------
redo size                                                            856160 ----- +411456

insert /*+append*/ into arch select 'ok' from dba_objects
29514 rows inserted

---- view redo engross space
NAME                                                                  VALUE
---------------------------------------------------------------- ----------
redo size                                                            870024 ----- +13864

insert /*+append*/ into arch1 select 'ok' from dba_objects
29514 rows inserted

---- view redo engross space
NAME                                                                  VALUE
---------------------------------------------------------------- ----------
redo size                                                            884004----- +13980
spool off;
posted @ 2010-10-28 14:56 xzc 阅读(3588) | 评论 (0)编辑 收藏
Java代码 复制代码
  1. shell判断文件,目录是否存在或者具有权限   
  2.   #!/bin/sh   
  3.   
  4. myPath="/var/log/httpd/"  
  5. myFile="/var /log/httpd/access.log"  
  6.   
  7. #这里的-x 参数判断$myPath是否存在并且是否具有可执行权限   
  8. if [ ! -x "$myPath"]; then   
  9. mkdir "$myPath"  
  10. fi   
  11.   
  12. #这里的-d 参数判断$myPath是否存在   
  13. if [ ! -d "$myPath"]; then   
  14. mkdir "$myPath"  
  15. fi   
  16.   
  17. #这里的-f参数判断$myFile是否存在   
  18. if [ ! -f "$myFile" ]; then   
  19. touch "$myFile"  
  20. fi   
  21.   
  22. #其他参数还有-n,-n是判断一个变量是否是否有值   
  23. if [ ! -n "$myVar" ]; then   
  24. echo "$myVar is empty"  
  25. exit 0  
  26. fi   
  27.   
  28. #两个变量判断是否相等   
  29. if [ "$var1" = "$var2" ]; then   
  30. echo '$var1 eq $var2'  
  31. else  
  32. echo '$var1 not eq $var2'  
  33. fi  
posted @ 2010-09-29 19:34 xzc 阅读(596) | 评论 (1)编辑 收藏
  • /**  
  •  * commons-net-2.0.jar是工程依赖包   
  •  */  
  • package telnet2;   
  •   
  • import java.io.InputStream;   
  • import java.io.PrintStream;   
  •   
  • import org.apache.commons.net.telnet.TelnetClient;   
  •   
  • /**  
  •  * @descript NetTelenet.java  
  •  * @author sinclair  
  •  * @date Jun 10, 2010  
  •  */  
  • public class NetTelnet {   
  •     private TelnetClient telnet = new TelnetClient();   
  •     private InputStream in;   
  •     private PrintStream out;   
  •     private char prompt = '$';// 普通用户结束   
  •   
  •     public NetTelnet( String ip, int port, String user, String password ) {   
  •     try {   
  •         telnet.connect( ip, port );   
  •         in = telnet.getInputStream();   
  •         out = new PrintStream( telnet.getOutputStream() );   
  •         // 根据root用户设置结束符   
  •         this.prompt = user.equals( "root" ) ? '#' : '$';   
  •         login( user, password );   
  •     } catch ( Exception e ) {   
  •         e.printStackTrace();   
  •     }   
  •     }   
  •   
  •     /**  
  •      * 登录  
  •      *   
  •      * @param user  
  •      * @param password  
  •      */  
  •     public void login( String user, String password ) {   
  •     readUntil( "login:" );   
  •     write( user );   
  •     readUntil( "Password:" );   
  •     write( password );   
  •     readUntil( prompt + " " );   
  •     }   
  •   
  •     /**  
  •      * 读取分析结果  
  •      *   
  •      * @param pattern  
  •      * @return  
  •      */  
  •     public String readUntil( String pattern ) {   
  •     try {   
  •         char lastChar = pattern.charAt( pattern.length() - 1 );   
  •         StringBuffer sb = new StringBuffer();   
  •         char ch = ( char ) in.read();   
  •         while ( true ) {   
  •         sb.append( ch );   
  •         if (ch == lastChar) {   
  •             if (sb.toString().endsWith( pattern )) {   
  •             return sb.toString();   
  •             }   
  •         }   
  •         ch = ( char ) in.read();   
  •         }   
  •     } catch ( Exception e ) {   
  •         e.printStackTrace();   
  •     }   
  •     return null;   
  •     }   
  •   
  •     /**  
  •      * 写操作  
  •      *   
  •      * @param value  
  •      */  
  •     public void write( String value ) {   
  •     try {   
  •         out.println( value );   
  •         out.flush();   
  •     } catch ( Exception e ) {   
  •         e.printStackTrace();   
  •     }   
  •     }   
  •   
  •     /**  
  •      * 向目标发送命令字符串  
  •      *   
  •      * @param command  
  •      * @return  
  •      */  
  •     public String sendCommand( String command ) {   
  •     try {   
  •         write( command );   
  •         return readUntil( prompt + " " );   
  •     } catch ( Exception e ) {   
  •         e.printStackTrace();   
  •     }   
  •     return null;   
  •     }   
  •   
  •     /**  
  •      * 关闭连接  
  •      */  
  •     public void disconnect() {   
  •     try {   
  •         telnet.disconnect();   
  •     } catch ( Exception e ) {   
  •         e.printStackTrace();   
  •     }   
  •     }   
  •   
  •     public static void main( String[] args ) {   
  •     try {   
  •         System.out.println( "启动Telnet..." );   
  •         String ip = "192.168.0.11";   
  •         int port = 23;   
  •         String user = "user";   
  •         String password = "111111";   
  •         NetTelnet telnet = new NetTelnet( ip, port, user, password );   
  •         telnet.sendCommand( "export LANG=en" );   
  •         String r1 = telnet.sendCommand( "cd /home/project/" );   
  •         String r2 = telnet.sendCommand( "pwd" );   
  •         String r3 = telnet.sendCommand( "sh a.sh" );   
  •   
  •         System.out.println( "显示结果" );   
  •         System.out.println( r1 );   
  •         System.out.println( r2 );   
  •         System.out.println( r3 );   
  •   
  •         telnet.disconnect();   
  •     } catch ( Exception e ) {   
  •         e.printStackTrace();   
  •     }   
  •     }   
  • }  
  • posted @ 2010-09-29 15:56 xzc 阅读(4424) | 评论 (0)编辑 收藏
    read一次可以为多个变量赋值——但一次只能读一行,比如:
        #!/bin/bash
        IFS=:
        read aa bb cc < /etc/passwd
        echo $aa $bb $cc
        (注:默认shell是无法将/etc/passwd中那些以冒号分割的字符串分割的,通过设置IFS可以实现这一点,详情见本文底部)
        我们将看到的结果是前两个变量被赋予了正确的值,最后一个变量被赋予了文件第一行剩下的所有值。(因为read一次只能读一行)
        而现实中如果一个文件保存了这样一个电话本:
        路人甲  13900000000
        主角A   23320000
        神秘人  12x0x0x0000
        旁白    85600000
        ……
        如果我们要写一个脚本来实现该电话本的查询,通常会这样写:
        #!/bin/bash
        while read name num
        do
        if [ $name = $1 ]
           then echo $num
        fi
        done
        当我们把想查询的人名作为参数来启动脚本,就可以看到他的号码,然后给他打骚扰电话……
        (关于while等流程控制语句,我会在稍后整理)
     
     
        抽取行
        head -x 文件               //抽取前x行
        tail -x 文件               //抽取末尾x行
        sed  -n xp 文件          //抽取文件中的第x行   注:这里的-n就是-n,不代表别的。
     
     
        抽取列
        cut -fx -dy 文件           //以y作为分隔符,抽取第x列
        awk -Fy '{print $x}' 文件  //以y作为分隔符,抽取第x列
                                   注:awk可以抽取多列,在指令中使用逗号分割,例:
                                   awk -F: '{print $3,$5}' /etc/passwd
                                            将会抽取文件中的第3列和第5列
     
     
        排序
        sort -ty +xn 文件          //以y作为分隔符,以第1+x列为基准排序
        注:如果使用了该指令,则不能在同一语句内使用其它参数,如有需要,只能在管道中再sort一次,如: sort +4n /etc/fstab | sort -r
             其它参数:  n  对数字排序
                       d   对字母排序
                       M   对月份排序(诸如JAN,FEB....DEC之类)
                       r   逆向
     
     
        $IFS
        很多时候我们并不需要指定分隔符,因为$IFS默认包含了空格,\t和换行符。
        只有遇到其它分隔符是我们才需要特别指定,比如$PATH和/etc/passwd中就是以冒号分割,遇到类似这种情况,我们才需要对$IFS进行指定。
    posted @ 2010-09-17 16:05 xzc 阅读(730) | 评论 (0)编辑 收藏

    这段时间学习shell整理的笔记

    第1章 文件安全与权限
     显示文件
        ls -l

    d   目录。
    l   符号链接(指向另一个文件
    s   套接字文件。
    b   块设备文件。
    c   字符设备文件。
    p   命名管道文件。

      创建一个文件:
         touch myfile

      更改文件权限:
         chmod [who] operator [permission] filenam
          who: u g o a
          operator:+ - =
          operator: r(4) w(2) x(1)

         chown -R owner file
         chgrp groupname file

         id 自己信息
         umask 002
         ln [-s] source_path target_path
           ln -s /usr/opt/monitor/regstar/reg.log /var/adm/logs/monitor.log

       $ H O M E中查找文件名符合* . t x t的文件
           $ find ~ -name "*.txt" -print
       $ H O M E中查找文件名以一个大写字母开头的文件
           $ find . -name "[A-Z]*" -print
       /etc目录中查找文件名以host开头的文件
           $ find /etc -name "host*" -print
       查找文件权限位为 7 5 5的文件
           $ find . -perm 755 -print
       在/apps目录下查找文件,但不希望在/ a p p s / b i n目录下查找
           $ find /apps -name "/apps/bin" -prune -o -print
       在 $ H O M E目录中查找文件属主为d a v e的文件
           $ find ~ -user dave -print
       在/apps目录下查找属于a c c t s用户组的文件
           $ find /apps -group accts -print
       查找没有有效所属用户组的所有文件
           $ fine/-nogroup-print
       查找属主帐户已经被删除的文件(在/ e t c / p a s s w d文件中没有有效帐户的文件)
           $ find /home -nouser -print
       查找更改时间在5日以内的文件
           $ find / -mtime -5 -print
       在/var/ a d m目录下查找更改时间在3日以前的文件
           $ find /var/adm -mtime +3 -print
       假设现在的时间是2 3 : 4 0,希望查找更改时间在两个小时以内的文件
           $ touch -t 03111750 file
           $ ls -l file
           $ find . -newer file -print
       为了在/ e t c目录下查找所有的符号链接文件
           $ find /etc -type l -print
       为了在当前目录下查找除目录以外的所有类型的文件
           $ find . ! -type d -print
       查找文件长度大于1 M字节的文件
           $ find . -size +1000000c -print
       查找文件长度恰好为1 0 0字节的文件
           $ find /home/apache -size 100c -print
       查找长度超过1 0块的文件(一块等于5 1 2字节)
           $ find . -size +10 -print
       在当前的文件系统中查找文件(不进入其他文件系统)
           $ find . -name "*.XC" -mount -print
       首先匹配所有的文件然后再进入子目录中查找
           $ find / -name "CON.FILE" -depth -print

      crontab 举例:  *(分钟) *(小时) *(每月的几日) *(月) *(每周星期几)

    第1列 分钟1~5 9
    第2列 小时1~2 3(0表示子夜)
    第3列 日1~3 1
    第4列 月1~1 2
    第5列 星期0~6(0表示星期天)
    第6列 要运行的命令

    -u   用户名。
    -e   编辑c r o n t a b文件。
    -l   列出c r o n t a b文件中的内容。
    -r   删除c r o n t a b文件。

         表示每晚的2 1 : 3 0运行/ a p p s / b i n目录下的c l e a n u p . s h
            30 21* * * /apps/bin/cleanup.sh
         每月1、1 0、2 2日的4 : 4 5运行/ a p p s / b i n目录下的b a c k u p . s h
            45 4 1,10,22 * * /apps/bin/backup.sh
         在每天1 8 : 0 0至2 3 : 0 0之间每隔3 0分钟运行/ a p p s / b i n目录下的d b c h e c k . sh
            0,30 18-23 * * * /apps/bin/dbcheck.sh
         表示每星期六的11 : 0 0 p m运行/ a p p s / b i n目录下的q t r e n d . s h
            0 23 * * 6 /apps/bin/qtrend.sh

         linux系统重起cron服务的方法为:/sbin/service crond  restart
         aix系统重起cron服务的方法为:kill -9 pid(cron服务),cron服务后自动重起。

     创建一个新的crontab文件:
         在 $ H O M E目录下的. p r o f i l e文件
            加入  EDITOR=vi; export EDITOR
            vi davecron                    建一个新的crontab文件    
     $ crontab davecron             提交crontab

     如果你正在运行一个进程,而且你觉得在退出帐户时该进程还不会结束,那么可以使用n o h u p命令
          nohup command &

     echo string

     定义变量:
        read name
          输入hello
        echo $name
     
    输入文件—标准输入 0
    输出文件—标准输出 1
    错误输出文件—标准错误 2

    command > filename 把把标准输出重定向到一个新文件中
    command > filename 2>&1 把把标准输出和标准错误一起重定向到一个文件中
    command 2 > filename 把把标准错误重定向到一个文件中
    command >> filename 2>&1 把把标准输出和标准错误一起重定向到一个文件中 (追加)

    &&左边的命令(命令1)返回真(即返回0,成功被执行后,&&右边的命令(命令2)才能够被执行
       mv who.ini awho.ini && echo "it's success

    sort file.txt 对文件排序
    --------------------------------------------------

    正则表达式介绍:
    ^ 只只匹配行首
    $ 只只匹配行尾
    * 只一个单字符后紧跟*,匹配0个或多个此单字符
    [ ] 只匹配[ ]内字符。可以是一个单字符,也可以是字符序列。可以使用 -
    表示[ ]内字符序列范围,如用[ 1 - 5 ]代替[ 1 2 3 4 5 ]
    \ 只用来屏蔽一个元字符的特殊含义。因为有时在 s h e l l中一些元字符有
    特殊含义。\可以使其失去应有意义
    . 只匹配任意单字符
    pattern \ { n \ } 只用来匹配前面pattern出现次数。n为次数
    pattern \ { n,\ } m 只含义同上,但次数最少为n
    pattern \ { n,m \ } 只含义同上,但pattern出现次数在n与m之间

     匹配以单词t r o u b l e结尾的所有行
        t r o u b l e $
     要匹配所有空行
        ^ $   
        ^ . $
     使用\屏蔽一个特殊字符的含义
     下列字符可以认为是特殊字符
         $ . ' " * [ ] ^ | () \ + ?

     注意^符号的使用,当直接用在第一个括号里,意指否定或不匹配括号里内容
        [ ^ 0 - 9 ]   匹配任一非数字型字符

     匹配字母A出现两次,并以B结尾
        A \ { 2 \ } B
     匹配A至少4次  
        A \ { 4 , \ } B
     A出现2次到4次之间
        A \ { 2 , 4 \ } B

     grep 查匹配的字符

    -c   只输出匹配行的计数。
    -i   不区分大小写(只适用于单字符)。
    -h   查询多文件时不显示文件名。
    -l   查询多文件时只输出包含匹配字符的文件名。
    -n   显示匹配行及行号。
    -s   不显示不存在或无匹配文本的错误信息。
    -v   显示不包含匹配文本的所有行。

     所有. d o c文件中查找字符串“s o r t”
         $ grep "sort" *.doc
     精确匹配
         $ grep "sort<tab>" *.doc
     抽取包含S e p t的所有月份,不管其大小写,并且此行包含字符串 4 8 3
         $ grep "[Ss]ept' data.f | grep 483
     对一个字符串使用grep
         str="hello every one"
         echo $str | grep "one"

     测试是否已设置或初始化变量。如果未设置或初始化,就可以使用另一值:
         $ { v a r i a b l e : - v a l u e }

    $ cu='chen'
    $ echo "the ask is ${cu:-hi} today" (如果未设置或初始化,就可以使用hi)

    readonly 变量  变量设置为只读

    设置环境变量:
       VARIABLE-NAME = v a l u e
       Export VARIABLE-NAME
    pg 分页显示
       变量 ARIABLE-NAME ='chen' 输出'chen'
       变量 ARIABLE-NAME ="chen" 输出 chen

    打印当前系统上用户数目:
       echo "ther are 'who | wc -l' users on the system "


    test测试:
    - d 目录             - s 文件长度大于0、非空
    - f 正规文件         - w 可写
    - L 符号连接         - u 文件有s u i d位设置
    - r 可读             - x 可执行

    test -r tt.txt
    echo $?   (正确显示0,错误显示1)


    确定当前的运行级别:
     $ who -r
     $ runlevel
    查看doc_part文件是否被打开,有哪些进程在使用:
     $ fuser -m /root/doc_part
    该命令可以显示当前所使用的登录用户名
      $ logname
    可以使用tty来报告所连接的设备或终端
      $tty
    记录当前会话
      $script. 文件名
      exit
    意味着系统在10秒钟之内不进行任何操作
      $sleep 10 
    可以看二进制文件中所包含的文本
      $strings 文件名
    whereis命令能够给出系统命令的二进制文件及其在线手册的路径
      $whereis  命令
    tr用法(字符转换)
      # tr -s "[a-z]" < a.txt >b.txt   a.txt的字符有重复的小写转为b.txt文件
      # cat da|tr -s "[a-z]"

      # tr -s "[\012]" < a.txt  去掉空行
      # tr -s "[\n]" < a.txt
      # tr -s "[\015\032]" "[\012*]"  < input_file  一般的dos到unix转换命令
      # echo "may May"|tr "[a-z]" "[A-Z]"    小写转大小
      # cat a.txt|tr "[a-z]" "[A-Z]" >b.txt
      # cat a.txt|tr "[A-Z]" "[a-z]" > b.txt 大小转小写
      # tr -cs "[a-z][A-Z]" "[\012*]" < a.txt  只保留大小字母,并分行

      sort分类:
      # sort a.txt > b.txt
      # uniq a.txt > b.txt 消除重复的行(只在行连续重复时才有效)
        # uniq -u a.txt   只显示不重复行
        # uniq -d a.txt   只显示有重复数据行
      join(将来自两个分类文本文件的行连在一起)
      # join a.txt b.txt
      # join -a1 a.txt b.txt      当有不匹配时,只显示a.txt
      # join -a1 -a2 a.txt b.txt  当有不匹配时,都显示出来
      split用来将大文件分割成小文件(将文件按每个最多1000行分割)
      # split 文件
      # split -100 文件  指定每个文件100行分割
      paste按行将不同文件行信息放在一行
      # ls | paste -d ""  以一列格式显示输出
      # paste a.txt b.txt
      cut用来从标准输入或文本文件中剪切列或
      # cut -c 1-3 c.txt          显示每行从开头算起1到3的字母
      # cut -c 1-2,5-10 c.txt     显示从1到2,还有5到10的字母
      # cut -f 1,3 c.txt          显示1和3栏的字符(使用tab分隔)

      sed用法:文本编辑器(强大的文本过滤工具)
      删除:d命令
         $ sed '2d' example-----删除example文件的第二行。
         $ sed '2,$d' example-----删除example文件的第二行到末尾所有行。
         $ sed '$d' example-----删除example文件的最后一行。
         $ sed '/test/'d example-----删除example文件所有包含test的行。
      替换:s命令
         $ sed 's/test/mytest/g' example-----在整行范围内把test替换为mytest。如果没有g标记,则只有每行第一个匹配的test被替换成mytest
         $ sed 's/^192.168.0.1/&localhost/' example-----&符号表示替换换字符串中被找到的部份。所有以192.168.0.1开头的行都会被替换成它自已加 localhost,变成192.168.0.1localhost
     写入文件:w命令
         $ sed -n '/test/w file' example  在example中所有包含test的行都被写入file里
         # sed '/^kai/a\\  this is a example' b.txt   " this is a example"被插入到以kai开头后面的新一行
         # sed '/^kai/i\\  this is a example' b.txt   " this is a example"被插入到以kai开头后面的前一行

    posted @ 2010-09-17 15:43 xzc 阅读(203) | 评论 (0)编辑 收藏

    转自:http://linuxtoy.org/archives/sed-awk.html
    sed 和 awk 都是 Linux 下常用的流编辑器,他们各有各的特色,本文并不是要做什么对比,而是权当好玩,把《SED 单行脚本快速参考》这文章,用 awk 做了一遍~ 至于孰好孰坏,那真是很难评论了。一般来说,sed 的命令会更短小一些,同时也更难读懂;而 awk 稍微长点,但是 if、while 这样的,逻辑性比较强,更加像“程序”。到底喜欢用哪个,就让各位看官自己决定吧!

    文本间隔:

    # 在每一行后面增加一空行

    sed G
    awk '{printf("%s\n\n",$0)}'
    

    # 将原来的所有空行删除并在每一行后面增加一空行。
    # 这样在输出的文本中每一行后面将有且只有一空行。

    sed '/^$/d;G'
    awk '!/^$/{printf("%s\n\n",$0)}'
    

    # 在每一行后面增加两行空行

    sed 'G;G'
    awk '{printf("%s\n\n\n",$0)}'
    

    # 将第一个脚本所产生的所有空行删除(即删除所有偶数行)

    sed 'n;d'
    awk '{f=!f;if(f)print $0}'
    

    # 在匹配式样“regex”的行之前插入一空行

    sed '/regex/{x;p;x;}'
    awk '{if(/regex/)printf("\n%s\n",$0);else print $0}'
    

    # 在匹配式样“regex”的行之后插入一空行

    sed '/regex/G'
    awk '{if(/regex/)printf("%s\n\n",$0);else print $0}'
    

    # 在匹配式样“regex”的行之前和之后各插入一空行

    sed '/regex/{x;p;x;G;}'
    awk '{if(/regex/)printf("\n%s\n\n",$0);else print $0}'
    

    编号:

    # 为文件中的每一行进行编号(简单的左对齐方式)。这里使用了“制表符”
    # (tab,见本文末尾关于’\t’的用法的描述)而不是空格来对齐边缘。

    sed = filename | sed 'N;s/\n/\t/'
    awk '{i++;printf("%d\t%s\n",i,$0)}'
    

    # 对文件中的所有行编号(行号在左,文字右端对齐)。

    sed = filename | sed 'N; s/^/     /; s/ *\(.\{6,\}\)\n/\1  /'
    awk '{i++;printf("%6d  %s\n",i,$0)}'
    

    # 对文件中的所有行编号,但只显示非空白行的行号。

    sed '/./=' filename | sed '/./N; s/\n/ /'
    awk '{i++;if(!/^$/)printf("%d %s\n",i,$0);else print}'
    

    # 计算行数 (模拟 “wc -l”)

    sed -n '$='
    awk '{i++}END{print i}'
    

    文本转换和替代:

    # Unix环境:转换DOS的新行符(CR/LF)为Unix格式。

    sed 's/.$//'                     # 假设所有行以CR/LF结束
    sed 's/^M$//'                    # 在bash/tcsh中,将按Ctrl-M改为按Ctrl-V
    sed 's/\x0D$//'                  # ssed、gsed 3.02.80,及更高版本
    awk '{sub(/\x0D$/,"");print $0}'
    

    # Unix环境:转换Unix的新行符(LF)为DOS格式。

    sed "s/$/`echo -e \\\r`/"        # 在ksh下所使用的命令
    sed 's/$'"/`echo \\\r`/"         # 在bash下所使用的命令
    sed "s/$/`echo \\\r`/"           # 在zsh下所使用的命令
    sed 's/$/\r/'                    # gsed 3.02.80 及更高版本
    awk '{printf("%s\r\n",$0)}'
    

    # DOS环境:转换Unix新行符(LF)为DOS格式。

    sed "s/$//"                      # 方法 1
    sed -n p                         # 方法 2
    

    DOS环境的略过

    # DOS环境:转换DOS新行符(CR/LF)为Unix格式。
    # 下面的脚本只对UnxUtils sed 4.0.7 及更高版本有效。要识别UnxUtils版本的
    # sed可以通过其特有的“–text”选项。你可以使用帮助选项(“–help”)看
    # 其中有无一个“–text”项以此来判断所使用的是否是UnxUtils版本。其它DOS
    # 版本的的sed则无法进行这一转换。但可以用“tr”来实现这一转换。

    sed "s/\r//" infile >outfile     # UnxUtils sed v4.0.7 或更高版本
    tr -d \r <infile >outfile        # GNU tr 1.22 或更高版本
    

    DOS环境的略过

    # 将每一行前导的“空白字符”(空格,制表符)删除
    # 使之左对齐

    sed 's/^[ \t]*//'                # 见本文末尾关于'\t'用法的描述
    awk '{sub(/^[ \t]+/,"");print $0}'
    

    # 将每一行拖尾的“空白字符”(空格,制表符)删除

    sed 's/[ \t]*$//'                # 见本文末尾关于'\t'用法的描述
    awk '{sub(/[ \t]+$/,"");print $0}'
    

    # 将每一行中的前导和拖尾的空白字符删除

    sed 's/^[ \t]*//;s/[ \t]*$//'
    awk '{sub(/^[ \t]+/,"");sub(/[ \t]+$/,"");print $0}'
    

    # 在每一行开头处插入5个空格(使全文向右移动5个字符的位置)

    sed 's/^/     /'
    awk '{printf("     %s\n",$0)}'
    

    # 以79个字符为宽度,将所有文本右对齐
    # 78个字符外加最后的一个空格

    sed -e :a -e 's/^.\{1,78\}$/ &/;ta'
    awk '{printf("%79s\n",$0)}'
    

    # 以79个字符为宽度,使所有文本居中。在方法1中,为了让文本居中每一行的前
    # 头和后头都填充了空格。 在方法2中,在居中文本的过程中只在文本的前面填充
    # 空格,并且最终这些空格将有一半会被删除。此外每一行的后头并未填充空格。

    sed  -e :a -e 's/^.\{1,77\}$/ & /;ta'                     # 方法1
    sed  -e :a -e 's/^.\{1,77\}$/ &/;ta' -e 's/\( *\)\1/\1/'  # 方法2
    awk '{for(i=0;i<39-length($0)/2;i++)printf(" ");printf("%s\n",$0)}'  #相当于上面的方法二
    

    # 在每一行中查找字串“foo”,并将找到的“foo”替换为“bar”

    sed 's/foo/bar/'                 # 只替换每一行中的第一个“foo”字串
    sed 's/foo/bar/4'                # 只替换每一行中的第四个“foo”字串
    sed 's/foo/bar/g'                # 将每一行中的所有“foo”都换成“bar”
    sed 's/\(.*\)foo\(.*foo\)/\1bar\2/' # 替换倒数第二个“foo”
    sed 's/\(.*\)foo/\1bar/'            # 替换最后一个“foo”
    awk '{gsub(/foo/,"bar");print $0}'   # 将每一行中的所有“foo”都换成“bar”
    

    # 只在行中出现字串“baz”的情况下将“foo”替换成“bar”

    sed '/baz/s/foo/bar/g'
    awk '{if(/baz/)gsub(/foo/,"bar");print $0}'
    

    # 将“foo”替换成“bar”,并且只在行中未出现字串“baz”的情况下替换

    sed '/baz/!s/foo/bar/g'
    awk '{if(/baz$/)gsub(/foo/,"bar");print $0}'
    

    # 不管是“scarlet”“ruby”还是“puce”,一律换成“red”

    sed 's/scarlet/red/g;s/ruby/red/g;s/puce/red/g'  #对多数的sed都有效
    gsed 's/scarlet\|ruby\|puce/red/g'               # 只对GNU sed有效
    awk '{gsub(/scarlet|ruby|puce/,"red");print $0}'
    

    # 倒置所有行,第一行成为最后一行,依次类推(模拟“tac”)。
    # 由于某些原因,使用下面命令时HHsed v1.5会将文件中的空行删除

    sed '1!G;h;$!d'               # 方法1
    sed -n '1!G;h;$p'             # 方法2
    awk '{A[i++]=$0}END{for(j=i-1;j>=0;j--)print A[j]}'
    

    # 将行中的字符逆序排列,第一个字成为最后一字,……(模拟“rev”)

    sed '/\n/!G;s/\(.\)\(.*\n\)/&\2\1/;//D;s/.//'
    awk '{for(i=length($0);i>0;i--)printf("%s",substr($0,i,1));printf("\n")}'
    

    # 将每两行连接成一行(类似“paste”)

    sed '$!N;s/\n/ /'
    awk '{f=!f;if(f)printf("%s",$0);else printf(" %s\n",$0)}'
    

    # 如果当前行以反斜杠“\”结束,则将下一行并到当前行末尾
    # 并去掉原来行尾的反斜杠

    sed -e :a -e '/\\$/N; s/\\\n//; ta'
    awk '{if(/\\$/)printf("%s",substr($0,0,length($0)-1));else printf("%s\n",$0)}'
    

    # 如果当前行以等号开头,将当前行并到上一行末尾
    # 并以单个空格代替原来行头的“=”

    sed -e :a -e '$!N;s/\n=/ /;ta' -e 'P;D'
    awk '{if(/^=/)printf(" %s",substr($0,2));else printf("%s%s",a,$0);a="\n"}END{printf("\n")}'
    

    # 为数字字串增加逗号分隔符号,将“1234567”改为“1,234,567”

    gsed ':a;s/\B[0-9]\{3\}\>/,&/;ta'                     # GNU sed
    sed -e :a -e 's/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/;ta'  # 其他sed
    

    #awk的正则没有后向匹配和引用,搞的比较狼狈,呵呵。

    awk '{while(match($0,/[0-9][0-9][0-9][0-9]+/)){$0=sprintf("%s,%s",substr($0,0,RSTART+RLENGTH-4),substr($0,RSTART+RLENGTH-3))}print $0}'
    

    # 为带有小数点和负号的数值增加逗号分隔符(GNU sed)

    gsed -r ':a;s/(^|[^0-9.])([0-9]+)([0-9]{3})/\1\2,\3/g;ta'
    

    #和上例差不多

    awk '{while(match($0,/[^\.0-9][0-9][0-9][0-9][0-9]+/)){$0=sprintf("%s,%s",substr($0,0,RSTART+RLENGTH-4),substr($0,RSTART+RLENGTH-3))}print $0}'
    

    # 在每5行后增加一空白行 (在第5,10,15,20,等行后增加一空白行)

    gsed '0~5G'                      # 只对GNU sed有效
    sed 'n;n;n;n;G;'                 # 其他sed
    awk '{print $0;i++;if(i==5){printf("\n");i=0}}'
    

    选择性地显示特定行:

    # 显示文件中的前10行 (模拟“head”的行为)

    sed 10q
    awk '{print;if(NR==10)exit}'
    

    # 显示文件中的第一行 (模拟“head -1”命令)

    sed q
    awk '{print;exit}'
    

    # 显示文件中的最后10行 (模拟“tail”)

    sed -e :a -e '$q;N;11,$D;ba'
    

    #用awk干这个有点亏,得全文缓存,对于大文件肯定很慢

    awk '{A[NR]=$0}END{for(i=NR-9;i<=NR;i++)print A[i]}'
    

    # 显示文件中的最后2行(模拟“tail -2”命令)

    sed '$!N;$!D'
    awk '{A[NR]=$0}END{for(i=NR-1;i<=NR;i++)print A[i]}'
    

    # 显示文件中的最后一行(模拟“tail -1”)

    sed '$!d'                        # 方法1
    sed -n '$p'                      # 方法2
    

    #这个比较好办,只存最后一行了。

    awk '{A=$0}END{print A}'
    

    # 显示文件中的倒数第二行

    sed -e '$!{h;d;}' -e x              # 当文件中只有一行时,输出空行
    sed -e '1{$q;}' -e '$!{h;d;}' -e x  # 当文件中只有一行时,显示该行
    sed -e '1{$d;}' -e '$!{h;d;}' -e x  # 当文件中只有一行时,不输出
    

    #存两行呗(当文件中只有一行时,输出空行)

    awk '{B=A;A=$0}END{print B}'
    

    # 只显示匹配正则表达式的行(模拟“grep”)

    sed -n '/regexp/p'               # 方法1
    sed '/regexp/!d'                 # 方法2
    awk '/regexp/{print}'
    

    # 只显示“不”匹配正则表达式的行(模拟“grep -v”)

    sed -n '/regexp/!p'              # 方法1,与前面的命令相对应
    sed '/regexp/d'                  # 方法2,类似的语法
    awk '!/regexp/{print}'
    

    # 查找“regexp”并将匹配行的上一行显示出来,但并不显示匹配行

    sed -n '/regexp/{g;1!p;};h'
    awk '/regexp/{print A}{A=$0}'
    

    # 查找“regexp”并将匹配行的下一行显示出来,但并不显示匹配行

    sed -n '/regexp/{n;p;}'
    awk '{if(A)print;A=0}/regexp/{A=1}'
    

    # 显示包含“regexp”的行及其前后行,并在第一行之前加上“regexp”所在行的行号 (类似“grep -A1 -B1”)

    sed -n -e '/regexp/{=;x;1!p;g;$!N;p;D;}' -e h
    awk '{if(F)print;F=0}/regexp/{print NR;print b;print;F=1}{b=$0}'
    

    # 显示包含“AAA”、“BBB”和“CCC”的行(任意次序)

    sed '/AAA/!d; /BBB/!d; /CCC/!d'   # 字串的次序不影响结果
    awk '{if(match($0,/AAA/) && match($0,/BBB/) && match($0,/CCC/))print}'
    

    # 显示包含“AAA”、“BBB”和“CCC”的行(固定次序)

    sed '/AAA.*BBB.*CCC/!d'
    awk '{if(match($0,/AAA.*BBB.*CCC/))print}'
    

    # 显示包含“AAA”“BBB”或“CCC”的行 (模拟“egrep”)

    sed -e '/AAA/b' -e '/BBB/b' -e '/CCC/b' -e d    # 多数sed
    gsed '/AAA\|BBB\|CCC/!d'                        # 对GNU sed有效
    awk '/AAA/{print;next}/BBB/{print;next}/CCC/{print}'
    awk '/AAA|BBB|CCC/{print}'
    

    # 显示包含“AAA”的段落 (段落间以空行分隔)
    # HHsed v1.5 必须在“x;”后加入“G;”,接下来的3个脚本都是这样

    sed -e '/./{H;$!d;}' -e 'x;/AAA/!d;'
    awk 'BEGIN{RS=""}/AAA/{print}'
    awk -vRS= '/AAA/{print}'
    

    # 显示包含“AAA”“BBB”和“CCC”三个字串的段落 (任意次序)

    sed -e '/./{H;$!d;}' -e 'x;/AAA/!d;/BBB/!d;/CCC/!d'
    awk -vRS= '{if(match($0,/AAA/) && match($0,/BBB/) && match($0,/CCC/))print}'
    

    # 显示包含“AAA”、“BBB”、“CCC”三者中任一字串的段落 (任意次序)

    sed -e '/./{H;$!d;}' -e 'x;/AAA/b' -e '/BBB/b' -e '/CCC/b' -e d
    gsed '/./{H;$!d;};x;/AAA\|BBB\|CCC/b;d'         # 只对GNU sed有效
    awk -vRS= '/AAA|BBB|CCC/{print "";print}'
    

    # 显示包含65个或以上字符的行

    sed -n '/^.\{65\}/p'
    

    cat ll.txt | awk '{if(length($0)>=65)print}'

    # 显示包含65个以下字符的行

    sed -n '/^.\{65\}/!p'            # 方法1,与上面的脚本相对应
    sed '/^.\{65\}/d'                # 方法2,更简便一点的方法
    awk '{if(length($0)<=65)print}'
    

    # 显示部分文本——从包含正则表达式的行开始到最后一行结束

    sed -n '/regexp/,$p'
    awk '/regexp/{F=1}{if(F)print}'
    

    # 显示部分文本——指定行号范围(从第8至第12行,含8和12行)

    sed -n '8,12p'                   # 方法1
    sed '8,12!d'                     # 方法2
    awk '{if(NR>=8 && NR<12)print}'
    

    # 显示第52行

    sed -n '52p'                     # 方法1
    sed '52!d'                       # 方法2
    sed '52q;d'                      # 方法3, 处理大文件时更有效率
    awk '{if(NR==52){print;exit}}'
    

    # 从第3行开始,每7行显示一次

    gsed -n '3~7p'                   # 只对GNU sed有效
    sed -n '3,${p;n;n;n;n;n;n;}'     # 其他sed
    awk '{if(NR==3)F=1}{if(F){i++;if(i%7==1)print}}'
    

    # 显示两个正则表达式之间的文本(包含)

    sed -n '/Iowa/,/Montana/p'       # 区分大小写方式
    awk '/Iowa/{F=1}{if(F)print}/Montana/{F=0}'
    

    选择性地删除特定行:

    # 显示通篇文档,除了两个正则表达式之间的内容

    sed '/Iowa/,/Montana/d'
    awk '/Iowa/{F=1}{if(!F)print}/Montana/{F=0}'
    

    # 删除文件中相邻的重复行(模拟“uniq”)
    # 只保留重复行中的第一行,其他行删除

    sed '$!N; /^\(.*\)\n\1$/!P; D'
    awk '{if($0!=B)print;B=$0}'
    

    # 删除文件中的重复行,不管有无相邻。注意hold space所能支持的缓存大小,或者使用GNU sed。

    sed -n 'G; s/\n/&&/; /^\([ -~]*\n\).*\n\1/d; s/\n//; h; P'  #bones7456注:我这里此命令并不能正常工作
    awk '{if(!($0 in B))print;B[$0]=1}'
    

    # 删除除重复行外的所有行(模拟“uniq -d”)

    sed '$!N; s/^\(.*\)\n\1$/\1/; t; D'
    awk '{if($0==B && $0!=l){print;l=$0}B=$0}'
    

    # 删除文件中开头的10行

    sed '1,10d'
    awk '{if(NR>10)print}'
    

    # 删除文件中的最后一行

    sed '$d'
    

    #awk在过程中并不知道文件一共有几行,所以只能通篇缓存,大文件可能不适合,下面两个也一样

    awk '{B[NR]=$0}END{for(i=0;i<=NR-1;i++)print B[i]}'
    

    # 删除文件中的最后两行

    sed 'N;$!P;$!D;$d'
    awk '{B[NR]=$0}END{for(i=0;i<=NR-2;i++)print B[i]}'
    

    # 删除文件中的最后10行

    sed -e :a -e '$d;N;2,10ba' -e 'P;D'   # 方法1
    sed -n -e :a -e '1,10!{P;N;D;};N;ba'  # 方法2
    awk '{B[NR]=$0}END{for(i=0;i<=NR-10;i++)print B[i]}'
    

    # 删除8的倍数行

    gsed '0~8d'                           # 只对GNU sed有效
    sed 'n;n;n;n;n;n;n;d;'                # 其他sed
    awk '{if(NR%8!=0)print}' |head
    

    # 删除匹配式样的行

    sed '/pattern/d'                      # 删除含pattern的行。当然pattern可以换成任何有效的正则表达式
    awk '{if(!match($0,/pattern/))print}'
    

    # 删除文件中的所有空行(与“grep ‘.’ ”效果相同)

    sed '/^$/d'                           # 方法1
    sed '/./!d'                           # 方法2
    awk '{if(!match($0,/^$/))print}'
    

    # 只保留多个相邻空行的第一行。并且删除文件顶部和尾部的空行。
    # (模拟“cat -s”)

    sed '/./,/^$/!d'        #方法1,删除文件顶部的空行,允许尾部保留一空行
    sed '/^$/N;/\n$/D'      #方法2,允许顶部保留一空行,尾部不留空行
    awk '{if(!match($0,/^$/)){print;F=1}else{if(F)print;F=0}}'  #同上面的方法2
    

    # 只保留多个相邻空行的前两行。

    sed '/^$/N;/\n$/N;//D'
    awk '{if(!match($0,/^$/)){print;F=0}else{if(F<2)print;F++}}'
    

    # 删除文件顶部的所有空行

    sed '/./,$!d'
    awk '{if(F || !match($0,/^$/)){print;F=1}}'
    

    # 删除文件尾部的所有空行

    sed -e :a -e '/^\n*$/{$d;N;ba' -e '}'  # 对所有sed有效
    sed -e :a -e '/^\n*$/N;/\n$/ba'        # 同上,但只对 gsed 3.02.*有效
    awk '/^.+$/{for(i=l;i<NR-1;i++)print "";print;l=NR}'
    

    # 删除每个段落的最后一行

    sed -n '/^$/{p;h;};/./{x;/./p;}'
    

    #很长,很ugly,应该有更好的办法

    awk -vRS= '{B=$0;l=0;f=1;while(match(B,/\n/)>0){print substr(B,l,RSTART-l-f);l=RSTART;sub(/\n/,"",B);f=0};print ""}'
    

    特殊应用:

    # 移除手册页(man page)中的nroff标记。在Unix System V或bash shell下使
    # 用’echo’命令时可能需要加上 -e 选项。

    sed "s/.`echo \\\b`//g"    # 外层的双括号是必须的(Unix环境)
    sed 's/.^H//g'             # 在bash或tcsh中, 按 Ctrl-V 再按 Ctrl-H
    sed 's/.\x08//g'           # sed 1.5,GNU sed,ssed所使用的十六进制的表示方法
    awk '{gsub(/.\x08/,"",$0);print}'
    

    # 提取新闻组或 e-mail 的邮件头

    sed '/^$/q'                # 删除第一行空行后的所有内容
    awk '{print}/^$/{exit}'
    

    # 提取新闻组或 e-mail 的正文部分

    sed '1,/^$/d'              # 删除第一行空行之前的所有内容
    awk '{if(F)print}/^$/{F=1}'
    

    # 从邮件头提取“Subject”(标题栏字段),并移除开头的“Subject:”字样

    sed '/^Subject: */!d; s///;q'
    awk '/^Subject:.*/{print substr($0,10)}/^$/{exit}'
    

    # 从邮件头获得回复地址

    sed '/^Reply-To:/q; /^From:/h; /./d;g;q'
    

    #好像是输出第一个Reply-To:开头的行?From是干啥用的?不清楚规则。。

    awk '/^Reply-To:.*/{print;exit}/^$/{exit}'
    

    # 获取邮件地址。在上一个脚本所产生的那一行邮件头的基础上进一步的将非电邮地址的部分剃除。(见上一脚本)

    sed 's/ *(.*)//; s/>.*//; s/.*[:<] *//'
    

    #取尖括号里的东西吧?

    awk -F'[<>]+' '{print $2}'
    

    # 在每一行开头加上一个尖括号和空格(引用信息)

    sed 's/^/> /'
    awk '{print "> " $0}'
    

    # 将每一行开头处的尖括号和空格删除(解除引用)

    sed 's/^> //'
    awk '/^> /{print substr($0,3)}'
    

    # 移除大部分的HTML标签(包括跨行标签)

    sed -e :a -e 's/<[^>]*>//g;/</N;//ba'
    awk '{gsub(/<[^>]*>/,"",$0);print}'
    

    # 将分成多卷的uuencode文件解码。移除文件头信息,只保留uuencode编码部分。
    # 文件必须以特定顺序传给sed。下面第一种版本的脚本可以直接在命令行下输入;
    # 第二种版本则可以放入一个带执行权限的shell脚本中。(由Rahul Dhesi的一
    # 个脚本修改而来。)

    sed '/^end/,/^begin/d' file1 file2 ... fileX | uudecode   # vers. 1
    sed '/^end/,/^begin/d' "$@" | uudecode                    # vers. 2
    

    #我不想装个uudecode验证,大致写个吧

    awk '/^end/{F=0}{if(F)print}/^begin/{F=1}' file1 file2 ... fileX
    

    # 将文件中的段落以字母顺序排序。段落间以(一行或多行)空行分隔。GNU sed使用
    # 字元“\v”来表示垂直制表符,这里用它来作为换行符的占位符——当然你也可以
    # 用其他未在文件中使用的字符来代替它。

    sed '/./{H;d;};x;s/\n/={NL}=/g' file | sort | sed '1s/={NL}=//;s/={NL}=/\n/g'
    gsed '/./{H;d};x;y/\n/\v/' file | sort | sed '1s/\v//;y/\v/\n/'
    awk -vRS= '{gsub(/\n/,"\v",$0);print}' ll.txt | sort | awk '{gsub(/\v/,"\n",$0);print;print ""}'
    

    # 分别压缩每个.TXT文件,压缩后删除原来的文件并将压缩后的.ZIP文件
    # 命名为与原来相同的名字(只是扩展名不同)。(DOS环境:“dir /b”
    # 显示不带路径的文件名)。

    echo @echo off >zipup.bat
    dir /b *.txt | sed "s/^\(.*\)\.TXT/pkzip -mo \1 \1.TXT/" >>zipup.bat
    

    DOS 环境再次略过,而且我觉得这里用 bash 的参数 ${i%.TXT}.zip 替换更帅。

    下面的一些 SED 说明略过,需要的朋友自行查看原文。

    posted @ 2010-09-17 15:23 xzc 阅读(342) | 评论 (1)编辑 收藏
    Statspack是Oracle自带的强大的性能分析工具。他可以对当前数据库的运行状况作出全面的分析(包括实例信息、PGA顾问信息、命中率、top sql、top 5 wait event等等),是个好东西吧!下面切入正题:

     

    1.以sysdba身份登陆,查看数据文件路径

       

    Sql代码 复制代码
    1. C:\Documents and Settings\Administrator>sqlplus / as sysdba   
    2.   
    3. SQL*Plus: Release 10.2.0.1.0 - Production on 星期三 4月 14 10:51:41 2010   
    4.   
    5. Copyright (c) 1982, 2005, Oracle.  All rights reserved.   
    6.   
    7.   
    8. 连接到:   
    9. Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production   
    10. With the Partitioning, OLAP and Data Mining options   
    11.   
    12. sys@AAA>show user;   
    13. USER 为 "SYS"  
    14. sys@AAA>select file_name from dba_data_files;   
    15.   
    16. FILE_NAME   
    17. --------------------------------------------------   
    18. D:\ORACLE\PRODUCT\10.2.0\ORADATA\AAA\USERS01.DBF   
    19. D:\ORACLE\PRODUCT\10.2.0\ORADATA\AAA\SYSAUX01.DBF   
    20. D:\ORACLE\PRODUCT\10.2.0\ORADATA\AAA\UNDOTBS01.DBF   
    21. D:\ORACLE\PRODUCT\10.2.0\ORADATA\AAA\SYSTEM01.DBF   
    22. D:\ORACLE\PRODUCT\10.2.0\ORADATA\AAA\BBB.DBF   
    23. D:\ORACLE\PRODUCT\10.2.0\ORADATA\AAA\PERFSTAT.DBF   
    24.   
    25. 已选择6行。  

     

    2.创建statspack存储数据的表空间,(注:statspack往往会产生大量的分析数据,所以表空间还是大点为好)。

      

    Sql代码 复制代码
    1. create tablespace perfstat datafile 'D:\ORACLE\PRODUCT\10.2.0\ORADATA\AAA\PERFSTAT.DBF' size 2G;  

     

    3.运行statspack安装脚本。默认位置在$oracle_home\rdbms\admin\spcreate.sql

      

       

    Sql代码 复制代码
    1. sys@AAA> @D:\oracle\product\10.2.0\db_1\RDBMS\ADMIN\spcreate.sql   
    2.   
    3. ...................   
    4.   
    5. 输入 perfstat_password 的值:  perfstat   
    6.   
    7. ...   
    8.   
    9. 输入 default_tablespace 的值:  perfstat   
    10. ..........   
    11. ..........   
    12. 输入 temporary_tablespace 的值: temp  
    13. ..........   
    14. ..........  

     

    安装完之后 会自动切换用户到perfstat下:

      

    Sql代码 复制代码
    1. PERFSTAT@AAA> show user;   
    2.   
    3. USER is "PERFSTAT"  

     

     安装完毕!

     

    4.接下来采样分析,设定一个job,每小时执行一次采样。

       首先查看当前DB中有没有正在运行的JOB:

      

    Sql代码 复制代码
    1. perfstat@AAA>select job,schema_user,next_date,interval,what from user_jobs;   
    2.   
    3. 未选定行  

     

    创建statspack采样的job,没每个小时采样一次。

      

    Sql代码 复制代码
    1. perfstat@AAA>variable job number;   
    2. perfstat@AAA>begin  
    3.   2  dbms_job.submit(:job,'statspack.snap;',trunc(sysdate+1/24,'hh24'),'trunc(sysdate+1/24,''hh24'')');   
    4.   3  commit;   
    5.   4  end;   
    6.   5  /   
    7.   
    8. PL/SQL 过程已成功完成。  

     

    查看当前正在运行的job有哪些?

      

    Sql代码 复制代码
    1. perfstat@AAA>select job as j,schema_user,next_date,interval,what from user_jobs;   
    2.         J SCHEMA_USER                    NEXT_DATE      INTERVAL   WHAT   
    3. ---------- ------------------------------ -------------- ---------- ----------   
    4.          1 PERFSTAT                       14-4月 -10     trunc(sysd statspack.   
    5.                                                          ate+1/24,' snap;   
    6.                                                          hh24')  

     

     

    5.由于statspack的采集和分析会做很多DB的分析,产生大量的分析数据,所以频繁的采样肯定会消耗系统性能,特别是在生产库中,所以当你建立了上面每小时执行一次的那个job,请务必在不需要的时候停止它。不然的话,这个失误可能会是致命的( statspack job每小时都会跑,永不停的跑下去,呵呵。),尤其在生产库中。

     

    明天凌晨,系统比较清闲,采样已经没多大意义(采样分析的最终目的是分析高峰时段的系统瓶颈),所以停止这个job.

       

    Sql代码 复制代码
    1. perfstat@AAA>variable job number;   
    2. perfstat@AAA>begin  
    3.   2  dbms_job.submit(:job,'dbms_job.broken(1,true);',trunc(sysdate+1),'null');   
    4.   3  commit;   
    5.   4  end;   
    6.   5  /   
    7.   
    8. PL/SQL 过程已成功完成。  

     

     

    6.几个小时候后,看看生成的哪些快照。

    Sql代码 复制代码
    1. perfstat@AAA>select snap_id,snap_time,startup_time from stats$snapshot;   
    2.   
    3.    SNAP_ID SNAP_TIME      STARTUP_TIME   
    4. ---------- -------------- --------------   
    5.          1 14-4月 -10     14-4月 -10   
    6.          2 14-4月 -10     14-4月 -10  

     

    7.设定任意两个快照,产生这段时间内的性能分析报告(此时需要跑spreport脚本,路径和刚才那个脚本一致)。

    Sql代码 复制代码
    1. perfstat@AAA>@D:\oracle\product\10.2.0\db_1\RDBMS\ADMIN\spreport.sql   
    2.   
    3. Current Instance   
    4. ~~~~~~~~~~~~~~~~   
    5.    DB Id    DB Name     Inst Num Instance   
    6. ----------- ------------ -------- ------------   
    7.  1858440386 AAA                 1 aaa   
    8.   
    9.   
    10.   
    11. Instances in this Statspack schema  
    12. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~   
    13.   
    14.    DB Id    Inst Num DB Name      Instance     Host   
    15. ----------- -------- ------------ ------------ ------------   
    16.  1858440386        1 AAA          aaa          6979580041BD   
    17.                                                490   
    18.   
    19. Using 1858440386 for database Id   
    20. Using          1 for instance number   
    21.   
    22.   
    23. Specify the number of days of snapshots to choose from  
    24. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~   
    25. Entering the number of days (n) will result in the most recent   
    26. (n) days of snapshots being listed.  Pressing <return> without   
    27. specifying a number lists all completed snapshots.   
    28.   
    29.   
    30.   
    31. Listing all Completed Snapshots   
    32.   
    33.                                                        Snap   
    34. Instance     DB Name        Snap Id   Snap Started    Level Comment   
    35. ------------ ------------ --------- ----------------- ----- -------------   
    36. aaa          AAA                  1 14 4月  2010 09:5     5   
    37.                                     2   
    38.                                   2 14 4月  2010 09:5     5   
    39.                                     3   
    40.                                   3 14 4月  2010 11:0     5   
    41.                                     0   
    42.   
    43.   
    44.   
    45. Specify the Begin and End Snapshot Ids   
    46. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~   
    47. 输入 begin_snap 的值:  1   
    48. Begin Snapshot Id specified: 1   
    49.   
    50. 输入 end_snap 的值:  2   
    51. End   Snapshot Id specified: 2   
    52.   
    53.   
    54.   
    55. Specify the Report Name  
    56. ~~~~~~~~~~~~~~~~~~~~~~~   
    57. The default report file name is sp_1_2.  To use this name,   
    58. press <returnto continue, otherwise enter an alternative.   
    59.   
    60. 输入 report_name 的值:  d:\myreport.txt  
    Sql代码 复制代码
    1. ...回车  

     

     

    8.完成后,会产生一个分析报告(d:\myreport.txt)。

    附件:报告的截取片段:

    Sql代码 复制代码
    1. STATSPACK report for  
    2.   
    3. Database    DB Id    Instance     Inst Num Startup Time    Release     RAC   
    4. ~~~~~~~~ ----------- ------------ -------- --------------- ----------- ---   
    5.           1858440386 aaa                 1 14-4月 -10 09:2 10.2.0.1.0  NO  
    6.                                            2   
    7.   
    8. Host  Name:   6979580041BD490  Num CPUs:    2        Phys Memory (MB):    3,326   
    9. ~~~~   
    10.   
    11. Snapshot       Snap Id     Snap Time      Sessions Curs/Sess Comment   
    12. ~~~~~~~~    ---------- ------------------ -------- --------- -------------------   
    13. Begin Snap:          1 14-4月 -10 09:52:22      15       4.3   
    14.   End Snap:          2 14-4月 -10 09:53:20      15       5.8   
    15.    Elapsed:                0.97 (mins)   
    16.   
    17. Cache Sizes                       Begin        End  
    18. ~~~~~~~~~~~                  ---------- ----------   
    19.                Buffer Cache:       184M             Std Block Size:         8K   
    20.            Shared Pool Size:       380M                 Log Buffer:     6,860K   
    21.   
    22. Load Profile                            Per Second       Per Transaction  
    23. ~~~~~~~~~~~~                       ---------------       ---------------   
    24.                   Redo size:             10,075.66            584,388.00   
    25.               Logical reads:                 58.41              3,388.00   
    26.               Block changes:                 18.81              1,091.00   
    27.              Physical reads:                  0.22                 13.00   
    28.             Physical writes:                  0.00                  0.00   
    29.                  User calls:                  0.52                 30.00   
    30.                      Parses:                  2.83                164.00   
    31.                 Hard parses:                  0.72                 42.00   
    32.                       Sorts:                  1.76                102.00   
    33.                      Logons:                  0.02                  1.00   
    34.                    Executes:                 10.88                631.00   
    35.                Transactions:                  0.02   
    36.   
    37.   % Blocks changed per Read:   32.20    Recursive Call %:    99.69   
    38.  Rollback per transaction %:    0.00       Rows per Sort:    70.69   
    39.   
    40. Instance Efficiency Percentages   
    41. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~   
    42.             Buffer Nowait %:  100.00       Redo NoWait %:  100.00   
    43.             Buffer  Hit   %:   99.62    In-memory Sort %:  100.00   
    44.             Library Hit   %:   90.06        Soft Parse %:   74.39   
    45.          Execute to Parse %:   74.01         Latch Hit %:  100.00   
    46. Parse CPU to Parse Elapsd %:   14.29     % Non-Parse CPU:   98.41   
    47.   
    48.  Shared Pool Statistics        Begin   End  
    49.                                ------  ------   
    50.              Memory Usage %:   21.05   20.98   
    51.     % SQL with executions>1:   54.05   60.06   
    52.   % Memory for SQL w/exec>1:   80.51   83.00   
    53.   
    54. Top 5 Timed Events                                                    Avg %Total   
    55. ~~~~~~~~~~~~~~~~~~                                                   wait   Call   
    56. Event                                            Waits    Time (s)   (ms)   Time  
    57. ----------------------------------------- ------------ ----------- ------ ------   
    58. CPU time                                                         1          70.7   
    59. control file sequential read                       189           0      1   23.6   
    60. db file sequential read                              8           0      3    2.5   
    61. control file parallel write                         27           0      1    1.9   
    62. log file sync                                        1           0      5     .6   
    63.   
    64. .....................   
    65. .........................   
    66. ...........................  

     

     9.若想删除某个快照,制定snapid直接delete

    Sql代码 复制代码
    1. delete stats$snapshot where snap_id=1;  

     

    若想删除所有快照 ,只保留statspack结构,执行@sptrunc。脚本路径也在rdbms/admin下。若想连statspack一起干掉,也可以,请执行下面的脚本:@spdrop

     

    从此你也可以利用statspack来了解当前数据库的运行状况了。 

    posted @ 2010-08-07 11:18 xzc 阅读(1345) | 评论 (0)编辑 收藏

    偶然间发现,几年前,冯老师关于statspack的一篇文章,写的不错,收下了先。

    http://www.dbanotes.net/Oracle/AboutStatspack.htm

     

    Statspack 是 Oracle 提供的一个实例级的Tuning工具。很多DBA都喜欢用这个工具来进行数据库的优化调整。不过在交流中发现很多朋友对这个工具的的运用还有一些 问题。下面就其中比较容易出问题的几个方面进行一下简单的分析。

    快照的采样时间间隔问题

    我们知道,Statspack的report实际上也就是对比两个快照 (Snapshot,也就是数据库当前状态 ) 得出的结果。

    一般情况下,专家建议生成Statspack报告的快照时间间隔为15-30分钟。

    试想,一个人去医院看病,医生对其测量体温,一般也就是5-10分钟左右就可以了, 为什么是这麽长的时间?因为5-10分钟这段时间基本可以近似的得到你的体温。如果时间过短,可能达不到既定的目的,测到的体温会偏低,时间过长,甚至长达几 个小时的话(假设有这种情况),病人可能都昏迷几次了 ;) 。

    对生成Statspack报告的快照时间间隔也是这样,如果两个Snap Time时间过短,数据 库的一些主要周期性事务可能还没有运行,信息收集不完全。如果间隔过长,数据一样会有偏差。

    假设如下的情况:系统一直正常,但是最近几天有用户反映,在A时间段应用程序执行 很慢。B时间段正常,而 A时间段有一个主要的事务X运行(也是用户使用到的事务)。 B时间段有另外一个比较消耗资源的事务Y在运行。A和B时间段的跨度比较大。本来你的 快照如果覆盖A时间段内就已经能够的收集到比较准确的数据了,但不巧的是,你的Report 所用的两个Snap ID的时间跨度太长,从而把B时间段内的统计数据也收集了进来。 Statspack 经过比较,“认为”事务Y是对系统有主要影响(这也会在Report上体现出来),而你,经过分析,认为Y才是罪魁祸首,接下来,你不遗余力的对Y进行了tuning......

    问题出现了!调整了B之后,用户继续报告,A时间段内系统不但没有变快,反而变得更慢,甚至不可忍受。这种情况是很危险 的,可能会对系统造成不同程序的损害。在比较严格的环境中,这已经构成了一次比较严重的事故。

    或许你也要承认,Statspack的快照的采样时间间隔还真需要重视呢......

    这是一个Oracle 8.1.7.0.1 版本下的Statspack报告:

                          Snap Id          Snap Time Sessions
    ------- ------------------ --------
    Begin Snap:            637 04-Aug-03 11:59:33       25
    End Snap:              646 04-Aug-03 16:29:06       25
    Elapsed:                        269.55 (mins)
    

    从中可以看到快照637和快照646之间为269.55 (mins)。这么长的时间跨度,即使数据库在一定时间间隔内有问题,在这里的体现也会有偏差。
    下面的这个Statspack 报告的时间有点不靠谱了:

    	                                                                Snap Length
    Start Id  End Id              Start Time  End Time                (Minutes)
    --------  --------  --------------------  --------------------  -----------
    314  1053        11-Dec-03 18:07:13  19-Dec-03 10:53:02      11,085.82
    

    11,085.82分钟? 这么长时间内的数据采集分析,怕是绝大部分内容都是不能相信的了。

    还要注意的是,我们说的时间间隔,是Begin Snap和End Snap之间的间隔,而不是相邻两个Snap 之间的间隔。对于Snap收集的间隔,建议以不要影响性能为准,收集的太过于频繁,会对性能和 存储都造成压力。对于所谓的15-30分钟,不能墨守成规。具体的环境下应该加以调整。

    以偏概全

    Statspack从本质上说,是对系统的性能统计数据进行采样,然后进行分析,采样,就会有偏差。如何消除偏差?统计学指出差值随样品个数的增加而降低。所以,只凭借一个Report文档就断定数据库的性能问题出在某处,是比较武断的做法(个别情况除外)。需要DBA创建多个Report,包括不同时间段,对比进行分析,这样才会起到很好的效果。在寻求技术支持的时候也最好能够多提交几份Report,便于支持人员迅速帮助解决问题。

    有关Timed_statistics参数

    虽然这算是一个低级的错误,还是很遗憾,常常看到一些朋友对这个参数的忽略.如果在 Timed_statistics的值设置为False的时候进行收集,可以说,收集到的东西用处不是很大 (我想你不会只想看一些实例名字、初始化参数之类的信息吧)。甚至可以说,如果该参数不设置为True,性能分析无从说起。

    你成了泄密者?

    Statspack 报告会汇集到你的数据库系统比较全面的信息,如果不对报告加以"伪装"就随意发布到一些技术论坛上寻求支持,无疑给一些黑客以可乘之机。你的数据库名字、实例名字、主机名、数据库版本号、兼容参数、关键的表名字、文件路径等等,尤其是关键的SQL都是黑客们或是恶意入侵者的最好的参考信息。

    商业竞争对手也可能正在对你的数据库虎视眈眈。

    如果你有意积极配合这些恶意窥探者,那么就把你的Statspack公之于众吧 :-)

    posted @ 2010-08-07 11:18 xzc 阅读(120) | 评论 (0)编辑 收藏

    大家在平时开发中,有时意外的删除过表,可能就是直接重新创建该表。在oracle10g中,可以用Flashback drop恢复用一个被删除(drop)了的对象,oracle自动将该对象放入回收站。Flashback drop恢复的原理也是利用oracle的回收站来恢复被删除(drop)的对象。

    回收站,是一个虚拟的容器,用于存放所有被删除的对象。其实,对于一个对象的删除,数据库仅仅是简单的重命名操作。

    数据库参数recyclebin设置为on.(即默认设置)。参数recyclebin为on,则表示把Drop的对象放入回收站。为off,则表示直接删除对象而不放入回收站。

    查看recyclebin值命令如:

    SQL> show parameter bin;

    NAME                         TYPE       VALUE

    ------------------------------------ ----------- ------------------------------

    recyclebin                        string     on

    在系统或会话级别中修改参数recyclebin值的命令为:

    SQL>alter system set recyclebin = on|off;

    SQL>alter session set recyclebin = on|off;

    查看回收站的相关信息视图有:recyclebin/user_recyclebin/dba_recyclebin.

    手动清除回收站的信息为:purge recyclebin(或purge table original_name);

    删除一张表而不想放入回收站的命令为:drop table table_name purge;

    示例1:

    1.查看用户下回收站的信息,此时回收站为空

    SQL>selectOBJECT_NAME,ORIGINAL_NAME,TYPEfromuser_recyclebin;
    OBJECT_NAME                   ORIGINAL_NAME TYPE           
    ------------------------------ ------------- ------
    2.
    创建测试表tab_test,并为该表增加ind_test索引
    SQL>createtabletab_testasselect*fromall_objects;
    Tablecreated
    SQL>createindexind_testontab_test(object_id);
    Indexcreated

    SQL> select count(*) from tab_test;

     COUNT(*)

    ----------

        40699
    3
    。用drop命令删除tab_test表
    SQL>droptabletab_test;

    Tabledropped
    4。查看用户回收站信息,此时会记录删除后的对象在回收站中的相关信息,此时还能正常操作回收站中的对象,但不能操作DDL/DML语句
    SQL>selectOBJECT_NAME,ORIGINAL_NAME,TYPEfromuser_recyclebin;

    OBJECT_NAME                   ORIGINAL_NAME TYPE           
    ------------------------------ ------------- ------
    BIN$a+iPOcq+QXiwUT8B3c3QoA==$0 IND_TEST      INDEX                    
    BIN$zFJjV8zFSlqbLecXbDeANQ==$0 TAB_TEST      TABLE                   

    SQL>selectcount(*)from"BIN$zFJjV8zFSlqbLecXbDeANQ==$0";

     COUNT(*)
    ----------
        
    40699

    SQL>deletefrom"BIN$zFJjV8zFSlqbLecXbDeANQ==$0";

    deletefrom"BIN$zFJjV8zFSlqbLecXbDeANQ==$0"
    ORA-
    38301:无法对回收站中的对象执行DDL/DML

    5.用flashback恢复表到删除之前的状态
    SQL>flashbacktabletab_testtobeforedrop;
    Done

    SQL> select count(*) from tab_test;

     COUNT(*)

    ----------

        40699

    6.恢复表的索引(此时表中的索引同时也被恢复了,只不过该索引还是保留回收站中的索引名称)

    SQL> select index_name from user_indexes where table_name = 'TAB_TEST';

    INDEX_NAME

    ------------------------------

    BIN$a+iPOcq+QXiwUT8B3c3QoA==$0

    SQL> alter index "BIN$a+iPOcq+QXiwUT8B3c3QoA==$0" rename to ind_test;

    Index altered

    SQL> select index_name from user_indexes where table_name = 'TAB_TEST';

    INDEX_NAME

    ------------------------------

    IND_TEST

    示例2:

    1.查看用户下回收站的信息,此时回收站为空

    SQL>selectOBJECT_NAME,ORIGINAL_NAME,TYPEfromuser_recyclebin;
    OBJECT_NAME                   ORIGINAL_NAME TYPE           
    ------------------------------ ------------- ------
    2.
    创建测试表test1,并输入数据
    SQL> create table test1(id number);

    Table created

    SQL> insert into test1 values(1);

    1 row inserted

    SQL> insert into test1 values(2);

    1 row inserted

    SQL> insert into test1 values(3);

    1 row inserted

    SQL> insert into test1 values(4);

    1 row inserted

    SQL> commit;

    Commit complete

    SQL> select count(*) from test1;

     COUNT(*)

    ----------

            4

    3.删除test1表,然后在重新创建test1表

    SQL> drop table test1;

    Table dropped

    SQL> create table test1(id number);

    Table created

    SQL> insert into test1 values(1);

    1 row inserted

    SQL> commit;

    Commit complete

    SQL> select count(*) from test1;

     COUNT(*)

    ----------

            1

    4.再次删除test1表

    SQL> drop table test1;

    Table dropped

    5.查询回收站信息(此时回收站中有两条test1表的数据)

    SQL>select*fromuser_recyclebin;

    OBJECT_NAME                   ORIGINAL_NAME  TYPE                     
    ------------------------------ --------------------
    BIN$Uk69X077TQWqQ0OQ3u1FdQ==$0 TEST1         TABLE                   
    BIN$kpG5ZWdlRUi/jO6X0EYP+A==$0 TEST1         TABLE 

    5.用flashback恢复表到删除之前的状态

    SQL> flashback table test1 to before drop;

    Done

    SQL> select count(*) from test1;

     COUNT(*)

    ----------

            1

    此时查看恢复后的test1,发现恢复到最近一次的信息,因此可说明多次删除后,在回收站中会存在多条与test1有关的数据,而用flashback table test1 to before drop命令恢复到的是test1表中最近一次删除的信息


    posted @ 2010-08-04 20:40 xzc 阅读(754) | 评论 (0)编辑 收藏
    仅列出标题
    共32页: First 上一页 11 12 13 14 15 16 17 18 19 下一页 Last