《CSDN 社区电子杂志——Oracle 杂志》




                                                                  目录

目录........................
《CSDN 社区电子杂志——Oracle 杂志》

     1.12.       使用方法: ............................................................................
《CSDN 社区电子杂志——Oracle 杂志》

            1.6.2.      CADORecordset .............................................................
《CSDN 社区电子杂志——Oracle 杂志》




                                       篇首寄语
    值此新春佳节即将到来之际,我们的《Oracle 杂志》第三期与大家见面了。我们仅以此作为
...
《CSDN 社区电子杂志——Oracle 杂志》


数据库实战

   一次诊断和解决 CPU 利用率高的问题分析
                                                        本文作者: A...
《CSDN 社区电子杂志——Oracle 杂志》
and v$session.paddr=v$process.addr
and v$process.spid in (PID);

    用 top 中占用 CPU 很高的进程的 PID 替换脚...
《CSDN 社区电子杂志——Oracle 杂志》
    SQL> SELECT latch#, name, gets, misses, sleeps
          FROM v$latch
          WHERE sleeps>...
《CSDN 社区电子杂志——Oracle 杂志》
           order by sleeps desc)
           where rownum < 5)) b
    where a.RELATIVE_FNO = b.dba...
《CSDN 社区电子杂志——Oracle 杂志》
    SQL> set autotrace trace explain
    SQL>SELECT                                         d.dom...
《CSDN 社区电子杂志——Oracle 杂志》

    发现存在问题的数据库中的 SERVICE 表上不知道怎么多出了 I_SERVICE_PRICEPLANID、

I_SERVICE_SERVICESPECID 、I_SERVICE_S...
《CSDN 社区电子杂志——Oracle 杂志》




作者简介:


照片          网名 coolyl
暂缺          CSDN eMag Oracle 电子杂志主编
            现任 itpub Oracle...
《CSDN 社区电子杂志——Oracle 杂志》




                  关于 cursor_sharing = similar
                                             本文...
《CSDN 社区电子杂志——Oracle 杂志》


    SQL> /


    NAME                                                      VALUE
    ----------...
《CSDN 社区电子杂志——Oracle 杂志》

    我们再来看分析表和字段信息后的表现
    SQL> analyze table t1 compute statistics for table for columns object_...
《CSDN 社区电子杂志——Oracle 杂志》
    parse count (hard)                                              1641 (重复执行没发
生变化)
    parse c...
《CSDN 社区电子杂志——Oracle 杂志》

这样避免了一味地如 force 一样转换成变量形式,因为有 histograms 的情况下转换成变量之后就容

易产生错误的执行计划,没有利用上统计信息。而 exact 呢,在没有 histo...
《CSDN 社区电子杂志——MS-SQL Server 杂志》




数据库设计

                       时空数据库设计
                                          本文作者: ...
《CSDN 社区电子杂志——MS-SQL Server 杂志》

1.3.2. 快照

    一个地理目标在某一特定时刻所占据的空间范围及其属性信息,或者说:时空对象在某一特

定的时刻所占据的空间范围及其相应的属性信息。举例来说,地图上绘制...
《CSDN 社区电子杂志——MS-SQL Server 杂志》

    从以上示意图中可以清晰地看出,每一个时空对象都是由多个快照记录所描述的。观察者的

每一次观察都是基于一个特定的观察时间的。例如,图示中的观察者应该看到对象一的快照 2 ...
《CSDN 社区电子杂志——MS-SQL Server 杂志》




1.8. 存储过程:

    利用 Oracle 中包变量的会话独立性,在包中建立以下几个基本的存储过程:设置当前观察时

间,获取当前观察时间,利用当前观察时间和传入的...
《CSDN 社区电子杂志——MS-SQL Server 杂志》

前的观察模式,重写 Snap_Filter 函数以支持多种观察模式。

     例如:

     【对象历史追溯模式】此时当前观察时间这一参数失效,Snap_Filter 的...
《CSDN 社区电子杂志——MS-SQL Server 杂志》


数据库管理

                       Oracle 中分区表的使用
                                           ...
《CSDN 社区电子杂志——MS-SQL Server 杂志》

create tablespace dinya_space01

datafile '/test/demo/oracle/demodata/dinya03.dnf' size 5...
《CSDN 社区电子杂志——MS-SQL Server 杂志》
 5      item_description varchar2(300),
 6      transaction_date date not null
 7 )
 8   p...
《CSDN 社区电子杂志——MS-SQL Server 杂志》

就是三个不同的表空间中。



1.1.3. 复合分区

     有时候我们需要根据范围分区后,每个分区内的数据再散列地分布在几个表空间中,这样我

们就要使用复合分区。复合分...
《CSDN 社区电子杂志——MS-SQL Server 杂志》
SQL> insert into dinya_test values(3,12, 'BOOKS',to_date('2006-05-30','yyyy-mm-dd'));
1 ro...
《CSDN 社区电子杂志——MS-SQL Server 杂志》

1.2.3. 更新分区表的记录:

SQL> update dinya_test partition(part_01) t set t.item_description='DES...
《CSDN 社区电子杂志——MS-SQL Server 杂志》

     上面例子删除了第二个分区 part_02 中的交易记录 ID 为 4 的一条记录,和更新数据相同,如

果指定了分区,而条件中的数据又不在该分区中时,将不会删除任何数据...
《CSDN 社区电子杂志——MS-SQL Server 杂志》
                 1 sorts (memory)
                 0 sorts (disk)
                 2 rows ...
《CSDN 社区电子杂志——MS-SQL Server 杂志》
              0 redo size
            420 bytes sent via SQL*Net to client
            309...
《CSDN 社区电子杂志——MS-SQL Server 杂志》

1.4.3. 删除分区:

SQL> alter table dinya_test drop partition part_01;
Table altered.
SQL>

  ...
《CSDN 社区电子杂志——MS-SQL Server 杂志》




数据库开发

              VC+ADO 开发 Oracle 应用程序

                                          ...
《CSDN 社区电子杂志——MS-SQL Server 杂志》




1.2. 建立 VC 工程

    在 D:建立 VCProg 文件夹

    打开 Microsoft Visual C++ 6.0

    菜单:[File]->...
《CSDN 社区电子杂志——MS-SQL Server 杂志》




    其余参数保持默认,直接点[Finish]按键,结束向导。




http://emag.csdn.net     - 31 -                20...
《CSDN 社区电子杂志——MS-SQL Server 杂志》




    点击 OK

    将前面下载并解压的四的文件拷贝到 D:VCProgOraApp 下,文件夹内容如下所示:




http://emag.csdn.net  ...
《CSDN 社区电子杂志——MS-SQL Server 杂志》




    Visual C++ 6.0 中,WorkSpace 视口中选择 FileView 选项卡,在 OraApp Files 节点上右键单击,

弹出的菜单中点击[Ad...
《CSDN 社区电子杂志——MS-SQL Server 杂志》




    选择拷贝过来的四个文件添加到当前工程中




http://emag.csdn.net   - 34 -                2005 年 1 月 1 ...
《CSDN 社区电子杂志——MS-SQL Server 杂志》




    打开并编辑 StdAfx.h 文件:

    添加:
    #import "C:Program FilesCommon FilesSystemADOmsado...
《CSDN 社区电子杂志——MS-SQL Server 杂志》



    COraApp::InitInstance()函数中 AfxEnableControlContainer();一行下添加如下代码:
        if(!AfxOl...
《CSDN 社区电子杂志——MS-SQL Server 杂志》




    至此,建立 VC 工程完毕。



1.3. 设计应用程序界面

    WorkSpace 视口中选择 Resource View,展开 Dialog 并双击 I...
《CSDN 社区电子杂志——MS-SQL Server 杂志》




    删除默认的确定和取消按钮,添加如下三个按钮,并将它们的 ID 分别设为 IDC_ADD /

IDC_DEL / IDC_SHOW:




http://emag...
《CSDN 社区电子杂志——MS-SQL Server 杂志》




    添加四个 Static Text,姓名、电话和 Email 的不需要设置 ID,photo 的 ID 设为 IDC_PHOTO




    添加三个 Edit ...
《CSDN 社区电子杂志——MS-SQL Server 杂志》




    还需要两个按钮,ID 分别设为 IDC_CONNECT/IDC_CREATETABLE,添加并调整布局,结

果如下所示:




    Ctrl+W 调出 MF...
《CSDN 社区电子杂志——MS-SQL Server 杂志》




    OK,至此,用户界面设计完成。



1.4. 填写代码

    在 IDD_ORAAPP_DIALOG 设计窗口中双击[连接]按钮,VC 弹出对话框提示创建响应...
《CSDN 社区电子杂志——MS-SQL Server 杂志》




    VC 自动转到 OraAppDlg 的代码窗口,光标在 OnConnect()函数中:




http://emag.csdn.net          - 42...
《CSDN 社区电子杂志——MS-SQL Server 杂志》



    我们先不在这里添加代码,先打开 OraAppDlg.h 文件,添加两个#include 和一个成员变量的

定义:




    转回到 OnConnect()函数...
《CSDN 社区电子杂志——MS-SQL Server 杂志》
    }



    OK,现在可以编译并运行一下程序看一下效果了,按[F5]->是[Yes],应该没有编译错误,弹

出对话框,点连接按钮,如果连接参数正确,会弹出成功建立连...
《CSDN 社区电子杂志——MS-SQL Server 杂志》

    点击 OK,并在 OnCreateTable()函数中添加如下代码:


    void COraAppDlg::OnCreatetable()
    {
     ...
《CSDN 社区电子杂志——MS-SQL Server 杂志》


        CADORecordset rs;   //定义 Recordset 对象
        rs.SetConnection(&m_con);     //为 ...
《CSDN 社区电子杂志——MS-SQL Server 杂志》
            1 SnowyWolf            12345678
    SnowyWolf@itpub.net                       ...
《CSDN 社区电子杂志——MS-SQL Server 杂志》
            AfxMessageBox("表中没有可以显示的记录,请先添加记录");
            rs.Close();
            retur...
《CSDN 社区电子杂志——MS-SQL Server 杂志》
        LPVOID pvData = NULL;
        if (hGlobal != NULL)
        {
             if ((pvD...
《CSDN 社区电子杂志——MS-SQL Server 杂志》

    调整一下 Dialog 的布局,[F5]编译并运行,最终效果如下所示:




1.5. 小结一下

    至此,VC+ADO 实现 Oracle 客户端应用程序的 D...
《CSDN 社区电子杂志——MS-SQL Server 杂志》

     添加、修改记录

     游标的自由移动

     ……



1.6. 两个封装类的说明

     下面对两个封装类的方法作简要的说明,更详细的说明请直接查看源...
《CSDN 社区电子杂志——MS-SQL Server 杂志》

IsOpen                                   判断记录集是否已打开

CanUpdate                           ...
《CSDN 社区电子杂志——MS-SQL Server 杂志》

1.8. 完整源代码下载

     http://www.snowywolf.net/MyFolder/Source/vcprog.rar




作者简介:

照片     ...
《CSDN 社区电子杂志——MS-SQL Server 杂志》


数据库探秘

                   深入了解 Oracle 数据字典

            ——深入了解 Oracle 数据字典,提高自学习 Oracle ...
《CSDN 社区电子杂志——MS-SQL Server 杂志》

    GV$视图的产生是为了满足 OPS 环境的需要,在 OPS 环境中,查询 GV$视图返回所有实例信

息,而每个 V$视图基于 GV$视图,增加了 INST_ID 列判断...
《CSDN 社区电子杂志——MS-SQL Server 杂志》

    然后基于 V_$视图的同义词被创建。

    所以,实际上通常我们访问的 V$视图,其实是指向 V_$视图的同义词。

    而 V_$视图是基于真正的 V$视图(这...
《CSDN 社区电子杂志——MS-SQL Server 杂志》

    这部分代码是写在 Oracle 应用程序中的,在内存中创建了 bootstrap$以后,Oracle 就可以从 file

1,block 377 上读取其他信息,创建重...
《CSDN 社区电子杂志——MS-SQL Server 杂志》
    select NUM , NAME , TYPE , VALUE , ISDEFAULT , ISSES_MODIFIABLE , ISSYS_MODIFIA
    BL...
Csdn Emag(Oracle)第三期
Csdn Emag(Oracle)第三期
Csdn Emag(Oracle)第三期
Csdn Emag(Oracle)第三期
Csdn Emag(Oracle)第三期
Csdn Emag(Oracle)第三期
Csdn Emag(Oracle)第三期
Csdn Emag(Oracle)第三期
Csdn Emag(Oracle)第三期
Csdn Emag(Oracle)第三期
Upcoming SlideShare
Loading in...5
×

Csdn Emag(Oracle)第三期

839

Published on

Published in: Technology, Business
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
839
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
19
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Csdn Emag(Oracle)第三期

  1. 1. 《CSDN 社区电子杂志——Oracle 杂志》 目录 目录......................................................................................................................i 篇首寄语........................................................................................................ - 1 - 数据库实战.................................................................................................... - 2 - 一次诊断和解决CPU利用率高的问题分析................................................ - 2 - 关于cursor_sharing = similar......................................................................... - 9 - 1.1. 实验现象 .........................................................................................................................- 9 - 1.2. 结论 ...............................................................................................................................- 12 - 数据库设计.................................................................................................. - 14 - 时空数据库设计.......................................................................................... - 14 - 1.1. 需求前提: ...................................................................................................................- 14 - 1.2. 实践环境: ...................................................................................................................- 14 - 1.3. 术语表: .......................................................................................................................- 14 - 1.3.1. 时空对象 ...............................................................................................................- 14 - 1.3.2. 快照 .......................................................................................................................- 15 - 1.4. 设计方向: ...................................................................................................................- 15 - 1.5. 技术要点: ...................................................................................................................- 15 - 1.6. 图形解说: ...................................................................................................................- 15 - 1.7. 数据表: .......................................................................................................................- 16 - 1.8. 存储过程: ...................................................................................................................- 17 - 1.9. 视图: ...........................................................................................................................- 17 - 1.10. 触发器: .......................................................................................................................- 17 - 1.11. 扩展与变化: ...............................................................................................................- 17 - 1.11.1. 支持多种观察模式。 ...........................................................................................- 17 - 1.11.2. 增加对象关系表以描述时空对象之间的联系....................................................- 18 - http://emag.csdn.net i 2005 年 1 月 1 期 总第 3 期
  2. 2. 《CSDN 社区电子杂志——Oracle 杂志》 1.12. 使用方法: ...................................................................................................................- 18 - 数据库管理.................................................................................................. - 19 - Oracle中分区表的使用 ............................................................................... - 19 - 1.1. 分区表的创建 ...............................................................................................................- 20 - 1.1.1. 范围分区 ...............................................................................................................- 20 - 1.1.2. Hash分区(散列分区) .......................................................................................- 21 - 1.1.3. 复合分区 ...............................................................................................................- 22 - 1.2. 分区表操作 ...................................................................................................................- 22 - 1.2.1. 插入记录: ...........................................................................................................- 22 - 1.2.2. 查询分区表记录: ...............................................................................................- 23 - 1.2.3. 更新分区表的记录: ...........................................................................................- 24 - 1.2.4. 删除分区表记录: ...............................................................................................- 24 - 1.3. 分区表索引的使用: ...................................................................................................- 25 - 1.3.1. 局部索引分区的建立: .......................................................................................- 25 - 1.3.2. 全局索引分区的建立。 .......................................................................................- 26 - 1.4. 分区表的维护: ...........................................................................................................- 27 - 1.4.1. 增加一个分区: ......................................................................................................- 27 - 1.4.2. 合并一个分区: ...................................................................................................- 27 - 1.4.3. 删除分区: ...........................................................................................................- 28 - 1.5. 总结: ...........................................................................................................................- 28 - 数据库开发.................................................................................................. - 29 - VC+ADO开发Oracle应用程序 .................................................................. - 29 - 1.1. 准备工作 .......................................................................................................................- 29 - 1.2. 建立VC工程..................................................................................................................- 30 - 1.3. 设计应用程序界面 .......................................................................................................- 37 - 1.4. 填写代码 .......................................................................................................................- 41 - 1.5. 小结一下 .......................................................................................................................- 50 - 1.6. 两个封装类的说明 .......................................................................................................- 51 - 1.6.1. CADOConnection..................................................................................................- 51 - http://emag.csdn.net ii 2005 年 1 月 1 期 总第 3 期
  3. 3. 《CSDN 社区电子杂志——Oracle 杂志》 1.6.2. CADORecordset ....................................................................................................- 51 - 1.7. 后续工作 .......................................................................................................................- 52 - 1.8. 完整源代码下载 ...........................................................................................................- 53 - 数据库探秘.................................................................................................. - 54 - 深入了解Oracle数据字典 ........................................................................... - 54 - 1.1. X$表 ..............................................................................................................................- 54 - 1.2. GV$和V$视图...............................................................................................................- 54 - 1.3. GV_$,V_$视图和V$,GV$同义词 ................................................................................- 55 - 1.4. 再进一步 .......................................................................................................................- 56 - 1.4.1. X$表 ......................................................................................................................- 56 - 1.4.2. GV$和V$视图.......................................................................................................- 57 - Oracle 10g 新特性 ...................................................................................... - 60 - 浅谈ORACLE 10G 闪回恢复区................................................................ - 60 - 1.1. 何为闪回恢复区 ...........................................................................................................- 60 - 1.2. 为何要用闪回恢复区?..................................................................................................- 61 - 1.3. 设定闪回恢复区 ...........................................................................................................- 61 - 1.4. 管理并监控闪回恢复区 ...............................................................................................- 62 - 1.5. 闪回恢复区中文件的保持策略 ...................................................................................- 65 - 1.6. 注意事项 .......................................................................................................................- 66 - 1.7. 结束语 ...........................................................................................................................- 66 - 1.8. 参考信息 .......................................................................................................................- 66 - http://emag.csdn.net iii 2005 年 1 月 1 期 总第 3 期
  4. 4. 《CSDN 社区电子杂志——Oracle 杂志》 篇首寄语 值此新春佳节即将到来之际,我们的《Oracle 杂志》第三期与大家见面了。我们仅以此作为 献给大家的新年贺礼。感谢大家一直以来对我们杂志的支持。 呵呵,严格来说并不该我来写这篇寄语,因为这一期杂志的主编是 dinya。前期的一些重要工 作都是他负责完成的。但是后来由于工作的关系,才临时由我来接手,完成剩下的一些组织工作。 所以,我想先感谢 dinya 为杂志所作的贡献。然后,我想感谢其他的几位编辑,正是大家的积 极支持和无私奉献,才使得我们的杂志能够在年底这个异常繁忙的时候如期发布。 他们是:biti_rainy,eygle,chanet,雪狼,Fenng,kamus,coolyl,bzszp。呵呵,如果大家看 过我们的前两期杂志,相信这几个名字应该都耳熟能详了吧。 此外,我还要在这里重点感谢一位网友,即《时空数据库设计》一文的作者——李宏。此前 我们的文章都是由我们的各位编辑亲自撰稿的。李宏是第一位向我们投稿并被采用的作者。这篇 文章对我们的杂志来说,具有非常重要的意义,它代表了网友对我们杂志的关注以及实际的支持 和贡献。我们希望能有越来越多的人,关注我们的杂志,参与建设我们的杂志。 我们欢迎大家为我们提出宝贵意见,欢迎大家为我们踊跃投稿! 请将稿件发到《Oracle杂志》的投稿信箱:emag_oracle@csdn.net. 您的稿件,我们将通过编辑及主编的审核,优先录用。 现 行 的 投 稿 奖 励 , 请 参 见 《 CSDN 社 区 电 子 杂 志 奖 励 制 度 》 http://blog.csdn.net/ccemp/archive/2005/01/07/244057.aspx。 《Oracle 杂志》的健康发展,需要您的支持! 最后,我们在这里向大家拜个早年,祝大家新年快乐,万事如意! 《CSDN 社区电子杂志——Oracle 杂志》编辑部 2005 年 1 月 http://emag.csdn.net -1- 2005 年 1 月 1 期 总第 3 期
  5. 5. 《CSDN 社区电子杂志——Oracle 杂志》 数据库实战 一次诊断和解决 CPU 利用率高的问题分析 本文作者: Allan (allan@itpub.net ) Oracle 数据库经常会遇到 CPU 利用率很高的情况,这种时候大都是数据库中存在着严重性能 低下的 SQL 语句,这种 SQL 语句大大的消耗了 CPU 资源,导致整个系统性能低下。当然,引起 严重性能低下的 SQL 语句的原因是多方面的,具体的原因要具体的来分析,下面通过一个实际的 案例来说明如何来诊断和解决 CPU 利用率高的这类问题。 操作系统:solairs8 数据库:Oracle9.2.0.4 问题描述:现场工程师汇报数据库非常慢,几乎所有应用操作均无法正常进行。 首先登陆主机,执行 top 发现 CPU 资源几乎消耗殆尽,存在很多占用 CPU 很高的进程,而内 存和 I/O 都不高,具体如下: last pid: 26136; load averages: 8.89, 8.91, 8.12 216 processes: 204 sleeping, 8 running, 4 on cpu CPU states: 0.6% idle, 97.3% user, 1.8% kernel, 0.2% iowait, 0.0% swap Memory: 8192M real, 1166M free, 14M swap in use, 8179M swap free PID USERNAME THR PRI NICE SIZE RES STATE TIME CPU COMMAND 25725 oracle 1 50 0 4550M 4508M cpu2 12:23 11.23% oracle 25774 oracle 1 41 0 4550M 4508M run 14:25 10.66% oracle 26016 oracle 1 31 0 4550M 4508M run 5:41 10.37% oracle 26010 oracle 1 41 0 4550M 4508M run 4:40 9.81% oracle 26014 oracle 1 51 0 4550M 4506M cpu6 4:19 9.76% oracle 25873 oracle 1 41 0 4550M 4508M run 12:10 9.45% oracle 25723 oracle 1 50 0 4550M 4508M run 15:09 9.40% oracle 26121 oracle 1 41 0 4550M 4506M cpu0 1:13 9.28% oracle 于是先查看数据库的告警日志 ALERT 文件,并没有发现有什么错误存在,日志显示数据库运 行正常,排除数据库本身存在问题。 然后查看这些占用 CPU 资源很高的 Oracle 进程究竟是在做什么操作,使用如下 SQL 语句: select sql_text,spid,v$session.program,process from v$sqlarea,v$session,v$process where v$sqlarea.address=v$session.sql_address and v$sqlarea.hash_value=v$session.sql_hash_value http://emag.csdn.net -2- 2005 年 1 月 1 期 总第 3 期
  6. 6. 《CSDN 社区电子杂志——Oracle 杂志》 and v$session.paddr=v$process.addr and v$process.spid in (PID); 用 top 中占用 CPU 很高的进程的 PID 替换脚本中的 PID,得到相应的 Oracle 进程所执行的 SQL 语句,发现占用 CPU 资源很高的进程都是执行同一个 SQL 语句: SELECT d.domainname,d.mswitchdomainid, a.SERVICEID,a.SERVICECODE,a.USERTYPE,a.STATUS,a.NOTIFYSTATUS,to_char(a.DATECREATED ,'yyyy-mm-dd hh24:mi:ss') DATECREATED,VIPFLAG,STATUS2,CUSTOMERTYPE,CUSTOMERID FROM service a, gatewayloc b, subbureaunumber c, mswitchdomain d WHERE b.mswitchdomainid = d.mswitchdomainid and b.gatewaysn = c.gatewaysn AND a.ServiceCode like c.code||'%' and a.serviceSpecID=1 and a.status!='4' and a.status!='10' and a.servicecode like '010987654321%' and SubsidiaryID=999999999 基本上可以肯定是这个 SQL 引起了系统 CPU 资源大量被占用,那究竟是什么原因造成这个 SQL 这么大量占用 CPU 资源呢,我们先来看看数据库的进程等待事件都有些什么: SQL> select sid,event,p1,p1text from v$session_wait; SID EVENT P1 P1TEXT ---------- ---------------------------------------------------------------- 12 latch free 4.3982E+12 address 36 latch free 4.3982E+12 address 37 latch free 4.3982E+12 address 84 latch free 4.3982E+12 address 102 latch free 4.3982E+12 address 101 latch free 4.3982E+12 address 85 latch free 4.3982E+12 address 106 latch free 4.3982E+12 address 155 latch free 4.3982E+12 address 151 latch free 4.3982E+12 address 149 latch free 4.3982E+12 address 147 latch free 4.3982E+12 address 1 pmon timer 300 duration 从上面的查询我们可以看出,大都是 latch free 的等待事件,然后接着查一下这些 latch 的等待 都是什么进程产生的: SQL> select spid from v$process where addr in (select paddr from v$session where sid in(84,102,101,106,155,151)); SPID ------------ 25774 26010 25873 25725 由此看出 latch free 这个等待事件导致了上面的那个 SQL 语句都在等待,占用了大量的 CPU 资源。我们来看看究竟主要是那种类型的 latch 的等待,根据下面的 SQL 语句: http://emag.csdn.net -3- 2005 年 1 月 1 期 总第 3 期
  7. 7. 《CSDN 社区电子杂志——Oracle 杂志》 SQL> SELECT latch#, name, gets, misses, sleeps FROM v$latch WHERE sleeps>0 ORDER BY sleeps; LATCH# NAME GETS MISSES SLEEPS ---------- ---------------------------------------------------------------- 15 messages 96876 20 1 159 library cache pin allocation 407322 43 1 132 dml lock allocation 194533 213 2 4 session allocation 304897 48 3 115 redo allocation 238031 286 4 17 enqueue hash chains 277510 85 5 7 session idle bit 2727264 314 16 158 library cache pin 3881788 5586 58 156 shared pool 2771629 6184 662 157 library cache 5637573 25246 801 98 cache buffers chains 1722750424 758400 109837 由上面的查询可以看出最主要的 latch 等待是 cache buffers chains,这个 latch 的等待表明数据 库存在单独的 BLOCK 的竞争这些 latch,我们来看这个 latch 存在的子 latch 及其对应的类型: SQL> SELECT addr, latch#, gets, misses, sleeps FROM v$latch_children WHERE sleeps>0 and latch# = 98 ORDER BY sleeps desc; ADDR LATCH# GETS MISSES SLEEPS ---------------- ---------- ---------- ---------- ---------- 000004000A3DFD10 98 10840661 82891 389 000004000A698C70 98 159510 2 244 0000040009B21738 98 104269771 34926 209 0000040009B227A8 98 107604659 35697 185 000004000A3E0D70 98 5447601 18922 156 000004000A6C2BD0 98 853375 7 134 0000040009B24888 98 85538409 25752 106 …………… 接着我们来查看 sleep 较多的子 latch 对应都有哪些对象: SQL> select distinct a.owner,a.segment_name,a.segment_type from dba_extents a, (select dbarfil,dbablk from x$bh where hladdr in (select addr from (select addr from v$latch_children http://emag.csdn.net -4- 2005 年 1 月 1 期 总第 3 期
  8. 8. 《CSDN 社区电子杂志——Oracle 杂志》 order by sleeps desc) where rownum < 5)) b where a.RELATIVE_FNO = b.dbarfil and a.BLOCK_ID <= b.dbablk and a.block_id + a.blocks > b.dbablk; OWNER SEGMENT_NAME SEGMENT_TYPE --------------------------------------------------------------------------- TEST I_SERVICE_SERVICESPECID INDEX TEST I_SERVICE_SUBSIDIARYID INDEX TEST SERVICE TABLE TEST MSWITCHDOMAIN TABLE TEST I_SERVICE_SC_S INDEX ………………… 我们看到在开始的那个 SQL 语句中的几个对象都有包括在内,于是来看看开始的那个 SQL 的 执行计划: SQL> set autotrace trace explain SQL>SELECT d.domainname,d.mswitchdomainid, a.SERVICEID,a.SERVICECODE,a.USERTYPE,a.STATUS,a.NOTIFYSTATUS,to_char(a.DATECREATED ,'yyyy-mm-dd hh24:mi:ss') DATECREATED,VIPFLAG,STATUS2,CUSTOMERTYPE,CUSTOMERID FROM service a, gatewayloc b, subbureaunumber c, mswitchdomain d WHERE b.mswitchdomainid = d.mswitchdomainid and b.gatewaysn = c.gatewaysn AND a.ServiceCode like c.code||'%' and a.serviceSpecID=1 and a.status!='4' and a.status!='10' and a.servicecode like '010987654321%' and SubsidiaryID=999999999; Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=CHOOSE 1 0 NESTED LOOPS 2 1 NESTED LOOPS 3 2 NESTED LOOPS 4 3 TABLE ACCESS (FULL) OF 'SUBBUREAUNUMBER' 5 3 TABLE ACCESS (BY INDEX ROWID) OF 'GATEWAYLOC' 6 5 INDEX (UNIQUE SCAN) OF 'PK_GATEWAYLOC' (UNIQUE) 7 2 TABLE ACCESS (BY INDEX ROWID) OF 'MSWITCHDOMAIN' 8 7 INDEX (UNIQUE SCAN) OF 'PK_MSWITCHDOMAIN' (UNIQUE) 9 1 TABLE ACCESS (BY INDEX ROWID) OF 'SERVICE' 10 9 AND-EQUAL 11 10 INDEX (RANGE SCAN) OF 'I_SERVICE_SERVICESPECID' (NON -UNIQUE) 12 10 INDEX (RANGE SCAN) OF 'I_SERVICE_SUBSIDIARYID' (NON- UNIQUE) 根据开始查到的引起 latch free 等待中的对象和 SQL 语句的执行计划,觉得 SERVICE 表上的 索引有问题,似乎存在了过多的扫描,于是将同样的 SQL 语句在别的地市的同样的数据库上执行 一下,查看相应的执行计划: http://emag.csdn.net -5- 2005 年 1 月 1 期 总第 3 期
  9. 9. 《CSDN 社区电子杂志——Oracle 杂志》 SQL> set autotrace trace explain SQL>SELECT d.domainname,d.mswitchdomainid, a.SERVICEID,a.SERVICECODE,a.USERTYPE,a.STATUS,a.NOTIFYSTATUS,to_char(a.DATECREATED ,'yyyy-mm-dd hh24:mi:ss') DATECREATED,VIPFLAG,STATUS2,CUSTOMERTYPE,CUSTOMERID FROM service a, gatewayloc b, subbureaunumber c, mswitchdomain d WHERE b.mswitchdomainid = d.mswitchdomainid and b.gatewaysn = c.gatewaysn AND a.ServiceCode like c.code||'%' and a.serviceSpecID=1 and a.status!='4' and a.status!='10' and a.servicecode like '010987654321%' and SubsidiaryID=999999999; Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=CHOOSE 1 0 TABLE ACCESS (BY INDEX ROWID) OF 'SERVICE' 2 1 NESTED LOOPS 3 2 NESTED LOOPS 4 3 NESTED LOOPS 5 4 TABLE ACCESS (FULL) OF 'SUBBUREAUNUMBER' 6 4 TABLE ACCESS (BY INDEX ROWID) OF 'GATEWAYLOC' 7 6 INDEX (UNIQUE SCAN) OF 'PK_GATEWAYLOC' (UNIQUE) 8 3 TABLE ACCESS (BY INDEX ROWID) OF 'MSWITCHDOMAIN' 9 8 INDEX (UNIQUE SCAN) OF 'PK_MSWITCHDOMAIN' (UNIQUE) 10 2 INDEX (RANGE SCAN) OF 'I_SERVICE_SC_S' (NON-UNIQUE) 对比两个执行计划,发现索引 I_SERVICE_SERVICESPECID 和 I_SERVICE_SUBSIDIARYID 是不应该走的,于是又对比了两个地方 SERVICE 表上的索引个数: SQL> select index_name from user_indexes where table_name='SERVICE'; INDEX_NAME ------------------------------ I_SERVICE_ACCOUNTNUM I_SERVICE_CID I_SERVICE_DATEACTIVATED I_SERVICE_PRICEPLANID I_SERVICE_SC_S I_SERVICE_SERVICECODE I_SERVICE_SERVICESPECID I_SERVICE_SUBSIDIARYID PK_SERVICE_SID SQL> select index_name from user_indexes where table_name='SERVICE'; INDEX_NAME ------------------------------ I_SERVICE_ACCOUNTNUM I_SERVICE_CID I_SERVICE_DATEACTIVATED I_SERVICE_SC_S I_SERVICE_SERVICECODE PK_SERVICE_SID http://emag.csdn.net -6- 2005 年 1 月 1 期 总第 3 期
  10. 10. 《CSDN 社区电子杂志——Oracle 杂志》 发现存在问题的数据库中的 SERVICE 表上不知道怎么多出了 I_SERVICE_PRICEPLANID、 I_SERVICE_SERVICESPECID 、I_SERVICE_SUBSIDIARYID 三个索引,而这些索引就是导致了 开始那个 SQL 语句用了不该用的索引,引起 latch free 等待和 CPU 占用很高的罪魁祸首,于是删 除了那三个索引,重新执行相应的 SQL 语句,很快就得出了结果,CPU 的利用率也马上下降为正 常了,观察结果如下: last pid: 26387; load averages: 1.61, 1.38, 1.21 195 processes: 194 sleeping, 1 on cpu CPU states: 96.2% idle, 1.6% user, 1.7% kernel, 0.5% iowait, 0.0% swap Memory: 8192M real, 1183M free, 14M swap in use, 8179M swap free PID USERNAME THR PRI NICE SIZE RES STATE TIME CPU COMMAND 26383 oracle 1 59 0 4550M 4506M sleep 0:12 4.52% oracle 409 root 15 59 0 7168K 7008K sleep 173.1H 0.53% picld 25653 oracle 1 59 0 4550M 4508M sleep 2:12 0.48% oracle 26384 root 1 59 0 2800K 1912K cpu2 0:00 0.21% top-3.5b8-sun4u 25569 oracle 1 59 0 4550M 4508M sleep 0:12 0.09% oracle 25717 oracle 1 59 0 4550M 4507M sleep 0:07 0.05% oracle 25571 oracle 1 59 0 4550M 4507M sleep 0:10 0.04% oracle 25681 oracle 1 59 0 4550M 4508M sleep 0:10 0.04% oracle 25544 oracle 1 58 0 4554M 4501M sleep 0:14 0.03% oracle 25703 oracle 1 59 0 4550M 4506M sleep 0:23 0.03% oracle ……………… 对于 CPU 利用率过高的情况,如果是 SQL 语句性能比较低下引起的基本上都可以按照这个思 路来诊断和解决问题,当然具体问题还得具体分析,解决问题的方法也有很多种,这里不过是抛 砖引玉一下,只要能最终达到我们解决问题的目的就可以了。 http://emag.csdn.net -7- 2005 年 1 月 1 期 总第 3 期
  11. 11. 《CSDN 社区电子杂志——Oracle 杂志》 作者简介: 照片 网名 coolyl 暂缺 CSDN eMag Oracle 电子杂志主编 现任 itpub Oracle 管理版版主。 擅长数据库的维护,对于数据库的安装,调整,备份方面有自己独到的经验。同时也给一些 国内的大型企业做过 oracle 的培训,有一定的培训经验。 曾做过很多大型项目的数据库维护和支持工作,对 oracle 的维护有相当多的实际经验,善于 现场解决问题。 曾任职于国内某大型软件企业做 oracle 数据库的技术支持,客户遍及全国各个行业,尤其是 电信,政府行业。 现任职于某外资电信企业华北区分公司,DBA,负责华北区 40 多个数据库系统的维护,对大 型数据库管理经验丰富。 《Oracle 数据库 DBA 专题技术精粹》一书的主编及主要作者. Mail地址: allan@itpub.net http://emag.csdn.net -8- 2005 年 1 月 1 期 总第 3 期
  12. 12. 《CSDN 社区电子杂志——Oracle 杂志》 关于 cursor_sharing = similar 本文作者: biti_rainy (biti_rainy@itpub.net) 摘要:本文通过简单实验来尝试说明 cursor_sharing=similar 的含义。 1.1. 实验现象 我们先看看在表没有分析无统计数据情况下的表现 SQL> alter session set cursor_sharing = similar; Session altered. SQL> select name,value from v$sysstat where name like '%parse%'; NAME VALUE ---------------------------------------------------------------- ---------- parse time cpu 4948 parse time elapsed 4468 parse count (total) 170148 parse count (hard) 1619 (硬分析次数) parse count (failures) 80 SQL> select count(*) from t where object_id = 1000; COUNT(*) ---------- 0 SQL> select name,value from v$sysstat where name like '%parse%'; NAME VALUE ---------------------------------------------------------------- ---------- parse time cpu 4948 parse time elapsed 4468 parse count (total) 170172 parse count (hard) 1620 parse count (failures) 80 http://emag.csdn.net -9- 2005 年 1 月 1 期 总第 3 期
  13. 13. 《CSDN 社区电子杂志——Oracle 杂志》 SQL> / NAME VALUE ---------------------------------------------------------------- ---------- parse time cpu 4948 parse time elapsed 4468 parse count (total) 170176 parse count (hard) 1620 parse count (failures) 80 SQL> select count(*) from t where object_id = 1000; COUNT(*) ---------- 0 SQL> select name,value from v$sysstat where name like '%parse%'; NAME VALUE ---------------------------------------------------------------- ---------- parse time cpu 4948 parse time elapsed 4468 parse count (total) 170178 parse count (hard) 1620 parse count (failures) 80 SQL> select count(*) from t where object_id = 1001; COUNT(*) ---------- 0 SQL> select name,value from v$sysstat where name like '%parse%'; NAME VALUE ---------------------------------------------------------------- ---------- parse time cpu 4948 parse time elapsed 4468 parse count (total) 170180 parse count (hard) 1620(即使 object_id 发生 变化依然没有硬解析) parse count (failures) 80 http://emag.csdn.net - 10 - 2005 年 1 月 1 期 总第 3 期
  14. 14. 《CSDN 社区电子杂志——Oracle 杂志》 我们再来看分析表和字段信息后的表现 SQL> analyze table t1 compute statistics for table for columns object_id; Table analyzed. SQL> select name,value from v$sysstat where name like '%parse%'; NAME VALUE ---------------------------------------------------------------- ---------- parse time cpu 4973 parse time elapsed 4495 parse count (total) 170982 parse count (hard) 1640 parse count (failures) 80 SQL> select count(*) from t1 where object_id = 5000; COUNT(*) ---------- 0 SQL> select name,value from v$sysstat where name like '%parse%'; NAME VALUE ---------------------------------------------------------------- ---------- parse time cpu 4973 parse time elapsed 4495 parse count (total) 170984 parse count (hard) 1641 parse count (failures) 80 SQL> select count(*) from t1 where object_id = 5000; COUNT(*) ---------- 0 SQL> select name,value from v$sysstat where name like '%parse%'; NAME VALUE ---------------------------------------------------------------- ---------- parse time cpu 4973 parse time elapsed 4495 parse count (total) 171008 http://emag.csdn.net - 11 - 2005 年 1 月 1 期 总第 3 期
  15. 15. 《CSDN 社区电子杂志——Oracle 杂志》 parse count (hard) 1641 (重复执行没发 生变化) parse count (failures) 80 SQL> select count(*) from t1 where object_id = 5001; COUNT(*) ---------- 0 SQL> select name,value from v$sysstat where name like '%parse%'; NAME VALUE ---------------------------------------------------------------- ---------- parse time cpu 4973 parse time elapsed 4495 parse count (total) 171010 parse count (hard) 1642 (当 object_id 变 化的时候产生硬分析) parse count (failures) 80 SQL> SQL> select sql_text,child_number from v$sql where sql_text like 'select count(*) from t1 where%'; SQL_TEXT ------------------------------------------------------------------------------ CHILD_NUMBER ------------ select count(*) from t1 where object_id = :"SYS_B_0" 0 select count(*) from t1 where object_id = :"SYS_B_0" 1 1.2. 结论 可以看出若存在 object_id 的 histograms ,则每次是不同的值的时候都产生硬解析 ,若不存在 histograms,则不产生硬解析。换句话说,当表的字段被分析过存在 histograms 的时候,similar 的 表现和 exact 一样,当表的字段没被分析,不存在 histograms 的时候,similar 的表现和 force 一样。 http://emag.csdn.net - 12 - 2005 年 1 月 1 期 总第 3 期
  16. 16. 《CSDN 社区电子杂志——Oracle 杂志》 这样避免了一味地如 force 一样转换成变量形式,因为有 histograms 的情况下转换成变量之后就容 易产生错误的执行计划,没有利用上统计信息。而 exact 呢,在没有 histograms 的情况下也要分别 产生硬解析,这样的话,由于执行计划不会受到数据分布的影响(因为没有统计信息)重新解析 是没有实质意义的。而 similar 则综合了两者的优点。 作者简介: 网名 coolyl Oracle 专家。有丰富的 Oracle 实践经验,对体系结构、备份恢复、SQL 优化、整体性能优化、Oracle Internal 都有深入研究。 个人教育和成长经历: 对数据库应用设计中如何正确地应用 oracle 特性以扬长避短具有深刻理解。 有丰富的 oracle 实践经验,对数据库的体系结构、备份恢复、sql 优化、数据库整体性能优化、 oracle internal 都有深入研究。 曾于某电信集成公司负责计费系统的开发,然后成为某系统集成公司的 DBA,再辗转在香港 一家跨国公司珠海研发中心担任技术负责人(公司主要产品就是 sql 与数据库优化工具,产品主要销 往欧洲和北美),此后成为自由职业者,为客户提供独立的 oracle 数据库的技术服务和高级性能调整 等培训,同时提供 ITPUB 华南和华东的培训。 目前服务于国内某大型电子商务网站,维护系统数据库并提供开发支持. 擅长的技术领域:oracle 目前的工作动态:alibaba DBA 个人Blog:http://blog.itpub.net/biti_riany E-mail:biti_rainy@itpub.net http://emag.csdn.net - 13 - 2005 年 1 月 1 期 总第 3 期
  17. 17. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 数据库设计 时空数据库设计 本文作者: 李宏(bfbd@sina.com) 1.1. 需求前提: 数据每年变化 1~2 次,软件预计生命周期 50 年 1.2. 实践环境: Oracle Spatial 1.3. 术语表: 时空对象,快照 1.3.1. 时空对象 一个地理目标从诞生到消亡所经历的空间和时间范围及其属性信息。这是一个为处理时空数 据方便而抽象出来的概念,相当于全信息模型中的全信息对象。为了理解时空对象,我们以二维 地物为例。二维地物在二维空间中占据一定的空间范围,表现为一个二维几何体,也就是它的几 何属性。如果再增加一条时间轴,成为(x,y,t)坐标系,并认为任何的空间对象都有诞生和消 亡,则这个二维地物就在(x,y,t)坐标系中占据了一定的三维空间。我们就把二维地物从诞生 到消亡这一时间段所占据的空间-时间范围称之为“时空对象”。同理,也可以将时空对象扩展为 三维的空间对象在时间维度上的延续,也就是四维对象。时空对象的属性信息是一张二维表。 http://emag.csdn.net - 14 - 2005 年 1 月 1 期 总第 3 期
  18. 18. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 1.3.2. 快照 一个地理目标在某一特定时刻所占据的空间范围及其属性信息,或者说:时空对象在某一特 定的时刻所占据的空间范围及其相应的属性信息。举例来说,地图上绘制了一个饭店的位置,大 小,这就是饭店的一个快照。因为饭店是从某一时刻才诞生的,又会在某一时刻消亡,而在诞生 和消亡之间,还可能会搬迁或扩建。所以地图上反映的仅仅是饭店在某一时刻的状态,所以称之 为饭店在某一时刻的快照或时空对象在某一特定时刻的快照。注意,快照总是对应于某一特定的 时刻,否则将失去快照的意义。快照的属性信息是时空对象属性信息表中的一条记录。 1.4. 设计方向: 以时空对象的概念组织空间数据和属性数据,使得对地物变迁历史的查询和分析成为可能。 对应用层屏蔽历史数据的处理过程,将历史数据的处理当作数据库模块的功能之一。 1.5. 技术要点: 1、 Oracle 包变量的会话独立性 2、 动态视图技术(基于函数的视图) 1.6. 图形解说: 观察方向 空间 时空对象(对象一) 快照 1 快照 2 快照 3 对象三 对象二 时间 对象诞生时间 当前观察时间 对象消亡时间 http://emag.csdn.net - 15 - 2005 年 1 月 1 期 总第 3 期
  19. 19. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 从以上示意图中可以清晰地看出,每一个时空对象都是由多个快照记录所描述的。观察者的 每一次观察都是基于一个特定的观察时间的。例如,图示中的观察者应该看到对象一的快照 2 和 对象三的快照 2,而无法看到对象二和对象一、三的其他快照记录。看不到对象二是因为在此观察 时间之前,对象二已经消亡。看不到对象一的快照 1 是因为对象一有更新的观察数据快照 2 可以 更好地近似反映对象二在当前观察时间所处的状态。 1.7. 数据表: 数据表的设计基于以上概念 表 1-1 对象表 表名(黑体+ Times New Roman,小五) Obj_id NUMBER 时空对象标识号 <PK> Start_time DATE 对象诞生时间 End_time DATE 对象消亡时间 Obj_Attr VARCHAR2(100) 对象属性数据 会因时间的流逝而发生 变化的属性信息。 快照记录表 Obj_id NUMBER 时空对象标识 <FK> 号 Snap_id NUMBER 快照数据的唯 <PK> 一序号 Snap_time DATE 快照时间 Snap_end DATE 快照结束时间 属于同一时空对象的最 近的下一条快照的快照 时间。设置此列的目的是 为了查询方便。 Geom. MDSYS.SDO_GEOMETRY 快照几何数据 Attr VARCHAR2(100) 快照属性数据 会因时间的流逝而发生 变化的属性信息。 http://emag.csdn.net - 16 - 2005 年 1 月 1 期 总第 3 期
  20. 20. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 1.8. 存储过程: 利用 Oracle 中包变量的会话独立性,在包中建立以下几个基本的存储过程:设置当前观察时 间,获取当前观察时间,利用当前观察时间和传入的 Snap_time,Snap_end 参数判断快照记录是否 可见(Snap_Filter)。 1.9. 视图: 建立在快照记录表上的视图,基于存储函数 Snap_Filter 实现对表中记录的筛选。传入参数为: Snap_time,Snap_End.,返回值为此快照是否可见。 SELECT Obj_id, Snap_time, Geom, Attr FROM 快照记录表 WHERE Snap_Filter(Snap_time, Snap_end) > 0; Obj_id NUMBER 时空对象标识号 Snap_time DATE 快照时间 Geom. MDSYS.SDO_GEOMETRY 快照几何数据 Attr VARCHAR2(100) 快照属性数据 1.10. 触发器: 视图上的触发器,使应用层用户可以在视图中插入,修改,删除数据。 要点: 1、维护表中数据时要避免出现时间悖论,造成时间逻辑混乱。 2、快照记录表中的 Snap_end 列的维护稍微麻烦一些,应小心谨慎。 1.11. 扩展与变化: 1.11.1. 支持多种观察模式。 为了查询功能的灵活性,可以增加几个扩展功能的存储过程:设置当前的观察模式,获取当 http://emag.csdn.net - 17 - 2005 年 1 月 1 期 总第 3 期
  21. 21. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 前的观察模式,重写 Snap_Filter 函数以支持多种观察模式。 例如: 【对象历史追溯模式】此时当前观察时间这一参数失效,Snap_Filter 的行为发生变化,视图 中看到的是某一(或某几个)指定对象的所有快照。这种模式便于对单个对象的整个历史变迁过 程加以追踪。 【时间段观察模式】此时需要设置的观察时间不是一个时间点,而是一个时间段。Snap_Filter 的返回值也有了更丰富的含义,可以用不同的数字(例如:1,2,4)表示某一快照记录在当前时 间段开始,结尾,中间的可见性。这种模式可以用于需要对两个不同时间点的数据进行比较的场 合。 1.11.2. 增加对象关系表以描述时空对象之间的联系 时空对象之间可能会有各种各样的联系,例如:变化,融合,分裂等。可通过以下表格加以 描述。 时空对象关系表 Obj_1 NUMBER 时空对象标识号 <PK><FK> Obj_2 NUMBER 时空对象标识号 <PK><FK> Relation_type NUMBER 关系类型 <PK> 1.12. 使用方法: 如果是查询最新信息,即观察时间为系统当前时间,则直接访问视图即可。 如果是查询历史数据,只需在数据连接会话中调用存储过程来设置当前观察时间,其效果是 所有视图中可见的记录集合都是当前观察时间点可见的记录,其他记录不会出现在视图中。 http://emag.csdn.net - 18 - 2005 年 1 月 1 期 总第 3 期
  22. 22. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 数据库管理 Oracle 中分区表的使用 本文作者Dinya (dinya20@tom.com) 摘要:在大量业务数据处理的项目中,可以考虑使用分区表来提高应用系统的性能并方便数 据管理,本文详细介绍了分区表的使用。 在大型的企业应用或企业级的数据库应用中,要处理的数据量通常可以达到几十到几百 GB, 有的甚至可以到 TB 级。虽然存储介质和数据处理技术的发展也很快,但是仍然不能满足用户的需 求,为了使用户的大量的数据在读写操作和查询中速度更快,Oracle 提供了对表和索引进行分区 的技术,以改善大型应用系统的性能。 使用分区的优点: 增强可用性:如果表的某个分区出现故障,表在其他分区的数据仍然可用; 维护方便:如果表的某个分区出现故障,需要修复数据,只修复该分区即可; 均衡 I/O:可以把不同的分区映射到磁盘以平衡 I/O,改善整个系统性能; 改善查询性能:对分区对象的查询可以仅搜索自己关心的分区,提高检索速度。 Oracle 数据库提供对表或索引的分区方法有三种: 范围分区 Hash 分区(散列分区) 复合分区 下面将以实例的方式分别对这三种分区方法来说明分区表的使用。为了测试方便,我们先建 三个表空间。 create tablespace dinya_space01 datafile '/test/demo/oracle/demodata/dinya01.dnf' size 50M create tablespace dinya_space01 datafile '/test/demo/oracle/demodata/dinya02.dnf' size 50M http://emag.csdn.net - 19 - 2005 年 1 月 1 期 总第 3 期
  23. 23. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 create tablespace dinya_space01 datafile '/test/demo/oracle/demodata/dinya03.dnf' size 50M 1.1. 分区表的创建 1.1.1. 范围分区 范围分区就是对数据表中的某个值的范围进行分区,根据某个值的范围,决定将该数据存储 在哪个分区上。如根据序号分区,根据业务记录的创建日期进行分区等。 需求描述:有一个物料交易表,表名:material_transactions。该表将来可能有千万级的数 据记录数。要求在建该表的时候使用分区表。这时候我们可以使用序号分区三个区,每个区中预 计存储三千万的数据,也可以使用日期分区,如每五年的数据存储在一个分区上。 根据交易记录的序号分区建表: SQL> create table dinya_test 2 ( 3 transaction_id number primary key, 4 item_id number(8) not null, 5 item_description varchar2(300), 6 transaction_date date not null 7 ) 8 partition by range (transaction_id) 9 ( 10 partition part_01 values less than(30000000) tablespace dinya_space01, 11 partition part_02 values less than(60000000) tablespace dinya_space02, 12 partition part_03 values less than(maxvalue) tablespace dinya_space03 13 ); Table created. 建 表 成 功 , 根 据 交 易 的 序 号 , 交 易 ID 在 三 千 万 以 下 的 记 录 将 存 储 在 第 一 个 表 空 间 dinya_space01 中,分区名为:par_01,在三千万到六千万之间的记录存储在第二个表空间: dinya_space02 中,分区名为:par_02,而交易 ID 在六千万以上的记录存储在第三个表空间 dinya_space03 中,分区名为 par_03. 根据交易日期分区建表: SQL> create table dinya_test 2 ( 3 transaction_id number primary key, 4 item_id number(8) not null, http://emag.csdn.net - 20 - 2005 年 1 月 1 期 总第 3 期
  24. 24. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 5 item_description varchar2(300), 6 transaction_date date not null 7 ) 8 partition by range (transaction_date) 9 ( 10 partition part_01 values less than(to_date('2006-01-01','yyyy-mm-dd')) tablespace dinya_space01, 11 partition part_02 values less than(to_date('2010-01-01','yyyy-mm-dd')) tablespace dinya_space02, 12 partition part_03 values less than(maxvalue) tablespace dinya_space03 13 ); Table created. 这样我们就分别建了以交易序号和交易日期来分区的分区表。每次插入数据的时候,系统将 根据指定的字段的值来自动将记录存储到制定的分区(表空间)中。 当然,我们还可以根据需求,使用两个字段的范围分布来分区,如 partition by range ( transaction_id ,transaction_date), 分区条件中的值也做相应的改变,请读者自行测试。 1.1.2. Hash 分区(散列分区) 散列分区为通过指定分区编号来均匀分布数据的一种分区类型,因为通过在 I/O 设备上进行 散列分区,使得这些分区大小一致。如将物料交易表的数据根据交易 ID 散列地存放在指定的三个 表空间中: SQL> create table dinya_test 2 ( 3 transaction_id number primary key, 4 item_id number(8) not null, 5 item_description varchar2(300), 6 transaction_date date 7 ) 8 partition by hash(transaction_id) 9 ( 10 partition part_01 tablespace dinya_space01, 11 partition part_02 tablespace dinya_space02, 12 partition part_03 tablespace dinya_space03 13 ); Table created. 建表成功,此时插入数据,系统将按 transaction_id 将记录散列地插入三个分区中,这里也 http://emag.csdn.net - 21 - 2005 年 1 月 1 期 总第 3 期
  25. 25. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 就是三个不同的表空间中。 1.1.3. 复合分区 有时候我们需要根据范围分区后,每个分区内的数据再散列地分布在几个表空间中,这样我 们就要使用复合分区。复合分区是先使用范围分区,然后在每个分区内再使用散列分区的一种分 区方法,如将物料交易的记录按时间分区,然后每个分区中的数据分三个子分区,将数据散列地 存储在三个指定的表空间中: SQL> create table dinya_test 2 ( 3 transaction_id number primary key, 4 item_id number(8) not null, 5 item_description varchar2(300), 6 transaction_date date 7 ) 8 partition by range(transaction_date)subpartition by hash(transaction_id) 9 subpartitions 3 store in (dinya_space01,dinya_space02,dinya_space03) 10 ( 11 partition part_01 values less than(to_date('2006-01-01','yyyy-mm-dd')), 12 partition part_02 values less than(to_date('2010-01-01','yyyy-mm-dd')), 13 partition part_03 values less than(maxvalue) 14 ); Table created. 该例中,先是根据交易日期进行范围分区,然后根据交易的 ID 将记录散列地存储在三个表空 间中。 1.2. 分区表操作 以上了解了三种分区表的建表方法,下面将使用实际的数据并针对按日期的范围分区来测试 分区表的数据记录的操作。 1.2.1. 插入记录: SQL> insert into dinya_test values(1,12,'BOOKS',sysdate); 1 row created. SQL> insert into dinya_test values(2,12, 'BOOKS',sysdate+30); 1 row created. http://emag.csdn.net - 22 - 2005 年 1 月 1 期 总第 3 期
  26. 26. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 SQL> insert into dinya_test values(3,12, 'BOOKS',to_date('2006-05-30','yyyy-mm-dd')); 1 row created. SQL> insert into dinya_test values(4,12, 'BOOKS',to_date('2007-06-23','yyyy-mm-dd')); 1 row created. SQL> insert into dinya_test values(5,12, 'BOOKS',to_date('2011-02-26','yyyy-mm-dd')); 1 row created. SQL> insert into dinya_test values(6,12, 'BOOKS',to_date('2011-04-30','yyyy-mm-dd')); 1 row created. SQL> commit; Commit complete. SQL> 按上面的建表结果,2006 年前的数据将存储在第一个分区 part_01 上,而 2006 年到 2010 年 的交易数据将存储在第二个分区 part_02 上,2010 年以后的记录存储在第三个分区 part_03 上。 1.2.2. 查询分区表记录: SQL> select * from dinya_test partition(part_01); TRANSACTION_ID ITEM_ID ITEM_DESCRIPTION TRANSACTION_DATE -------------------------------------------------------------------------------- 1 12 BOOKS 2005-1-14 14:19: 2 12 BOOKS 2005-2-13 14:19: SQL> SQL> select * from dinya_test partition(part_02); TRANSACTION_ID ITEM_ID ITEM_DESCRIPTION TRANSACTION_DATE -------------------------------------------------------------------------------- 3 12 BOOKS 2006-5-30 4 12 BOOKS 2007-6-23 SQL> SQL> select * from dinya_test partition(part_03); TRANSACTION_ID ITEM_ID ITEM_DESCRIPTION TRANSACTION_DATE -------------------------------------------------------------------------------- 5 12 BOOKS 2011-2-26 6 12 BOOKS 2011-4-30 SQL> 从查询的结果可以看出,插入的数据已经根据交易时间范围存储在不同的分区中。这里是指 定了分区的查询,当然也可以不指定分区,直接执行 select * from dinya_test 查询全部记录。 在也检索的数据量很大的时候,指定分区会大大提高检索速度。 http://emag.csdn.net - 23 - 2005 年 1 月 1 期 总第 3 期
  27. 27. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 1.2.3. 更新分区表的记录: SQL> update dinya_test partition(part_01) t set t.item_description='DESK' where t.transaction_id=1; 1 row updated. SQL> commit; Commit complete. SQL> 这里将第一个分区中的交易 ID=1 的记录中的 item_description 字段更新为“DESK”,可以看 到已经成功更新了一条记录。但是当更新的时候指定了分区,而根据查询的记录不在该分区中时, 将不会更新数据,请看下面的例子: SQL> update dinya_test partition(part_01) t set t.item_description='DESK' where t.transaction_id=6; 0 rows updated. SQL> commit; Commit complete. SQL> 指定了在第一个分区中更新记录,但是条件中限制交易 ID 为 6,而查询全表,交易 ID 为 6 的 记录在第三个分区中,这样该条语句将不会更新记录。 1.2.4. 删除分区表记录: SQL> delete from dinya_test partition(part_02) t where t.transaction_id=4; 1 row deleted. SQL> commit; Commit complete. SQL> http://emag.csdn.net - 24 - 2005 年 1 月 1 期 总第 3 期
  28. 28. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 上面例子删除了第二个分区 part_02 中的交易记录 ID 为 4 的一条记录,和更新数据相同,如 果指定了分区,而条件中的数据又不在该分区中时,将不会删除任何数据。 1.3. 分区表索引的使用: 分区表和一般表一样可以建立索引,分区表可以创建局部索引和全局索引。当分区中出现许 多事务并且要保证所有分区中的数据记录的唯一性时采用全局索引。 1.3.1. 局部索引分区的建立: SQL> create index dinya_idx_t on dinya_test(item_id) 2 local 3 ( 4 partition idx_1 tablespace dinya_space01, 5 partition idx_2 tablespace dinya_space02, 6 partition idx_3 tablespace dinya_space03 7 ); Index created. SQL> 看查询的执行计划,从下面的执行计划可以看出,系统已经使用了索引: SQL> select * from dinya_test partition(part_01) t where t.item_id=12; Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=187) 1 0 TABLE ACCESS (BY LOCAL INDEX ROWID) OF 'DINYA_TEST' (Cost= 2 Card=1 Bytes=187) 2 1 INDEX (RANGE SCAN) OF 'DINYA_IDX_T' (NON-UNIQUE) (Cost=1 Card=1) Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 4 consistent gets 0 physical reads 0 redo size 334 bytes sent via SQL*Net to client 309 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client http://emag.csdn.net - 25 - 2005 年 1 月 1 期 总第 3 期
  29. 29. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 1 sorts (memory) 0 sorts (disk) 2 rows processed SQL> 1.3.2. 全局索引分区的建立。 全局索引建立时 global 子句允许指定索引的范围值,这个范围值为索引字段的范围值: SQL> create index dinya_idx_t on dinya_test(item_id) 2 global partition by range(item_id) 3 ( 4 partition idx_1 values less than (1000) tablespace dinya_space01, 5 partition idx_2 values less than (10000) tablespace dinya_space02, 6 partition idx_3 values less than (maxvalue) tablespace dinya_space03 7 ); Index created. SQL> 本例中对表的 item_id 字段建立索引分区,当然也可以不指定索引分区名直接对整个表建立 索引,如: SQL> create index dinya_idx_t on dinya_test(item_id); Index created. SQL> 同样的,对全局索引根据执行计划可以看出索引已经可以使用: SQL> select * from dinya_test t where t.item_id=12; Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=3 Bytes=561) 1 0 TABLE ACCESS (BY GLOBAL INDEX ROWID) OF 'DINYA_TEST' (Cost =2 Card=3 Bytes=561) 2 1 INDEX (RANGE SCAN) OF 'DINYA_IDX_T' (NON-UNIQUE) (Cost=1 Card=3) Statistics ---------------------------------------------------------- 5 recursive calls 0 db block gets 10 consistent gets 0 physical reads http://emag.csdn.net - 26 - 2005 年 1 月 1 期 总第 3 期
  30. 30. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 0 redo size 420 bytes sent via SQL*Net to client 309 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 3 sorts (memory) 0 sorts (disk) 5 rows processed SQL> 1.4. 分区表的维护: 了解了分区表的建立、索引的建立、表和索引的使用后,在应用的还要经常对分区进行维护 和管理。日常维护和管理的内容包括:增加一个分区,合并一个分区及删除分区等等。下面以范 围分区为例说明增加、合并、删除分区的一般操作: 1.4.1. 增加一个分区: SQL> alter table dinya_test 2 add partition part_04 values less than(to_date('2012-01-01','yyyy-mm-dd')) tablespace dinya_spa ce03; Table altered. SQL> 增加一个分区的时候,增加的分区的条件必须大于现有分区的最大值,否则系统将提示 ORA-14074 partition bound must collate higher than that of the last partition 错误。 1.4.2. 合并一个分区: SQL> alter table dinya_test merge partitions part_01,part_02 into partition part_02; Table altered. SQL> 在本例中将原有的表的part_01 分区和part_02 分区进行了合并,合并后的分区为part_02,如 果在合并的 时候把合并 后的分区定 为part_01 的时候,系 统将提示ORA-14275 cannot reuse lower-bound partition as resulting partition 错误。 http://emag.csdn.net - 27 - 2005 年 1 月 1 期 总第 3 期
  31. 31. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 1.4.3. 删除分区: SQL> alter table dinya_test drop partition part_01; Table altered. SQL> 删除分区表的一个分区后,查询该表的数据时显示,该分区中的数据已全部丢失,所以执行 删除分区动作时要慎重,确保先备份数据后再执行,或将分区合并。 1.5. 总结: 需要说明的是,本文在举例说名分区表事务操作的时候,都指定了分区,因为指定了分区, 系统在执行的时候则只操作该分区的记录,提高了数据处理的速度。不要指定分区直接操作数据 也是可以的。在分区表上建索引及多索引的使用和非分区表一样。此外,因为在维护分区的时候 可能对分区的索引会产生一定的影响,可能需要在维护之后重建索引,相关内容请参考分区表索 引部分的文档。 作者简介: 姓名:丁亚军 网名:dinya 曾做 Windows 程序开发。 现就职于一家制造企业,做 Oracle ERP 二次开发工作,对 Oracle ERP 二次开发和 Oracle 数据 库开发有一定研究,现任 CSDN 论坛 Oracle 开发版版主,CSDN 社区 Oracle 电子杂志编辑。 作者Mail:dinya20@tom.com 作者Blog:http://blog.csdn.net/dinya2003/ 个人Blog:http://blog.itpub.net/biti_riany E-mail:biti_rainy@itpub.net http://emag.csdn.net - 28 - 2005 年 1 月 1 期 总第 3 期
  32. 32. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 数据库开发 VC+ADO 开发 Oracle 应用程序 ——Oracle 应用程序开发(一) 本文作者: SnowyWolf (SnowyWolf@itpub.net ) 摘要:本文提供了建立 Oracle 客户端应用程序的一种方式――使用 Visual C++ 6.0 和 ADO 接 口来访问 Oracle 数据库,并封装了两个实用类。 经常有朋友问如何将图片或文件存入 Oracle 数据库,也有朋友问如何操作 Oracle 中的 BLOB 字段,解决类似的问题有很多方法,VC+ADO 开发 Oracle 客户端应用程序即是一种不错的解决方 案。 可能很多朋友感觉 VC 很难,ADO 很麻烦,其实不然。本文通过一个 Demo,一步一步给您 演示使用 VC+ADO 开发 Oracle 客户端应用程序的步骤。 本文适用读者:有一定的 VC 开发经验,熟悉 Oracle 基本概念 难度等级:中级 1.1. 准备工作 要顺利完成本文的 Demo,您需要做好如下的准备工作: 硬件:一台 PC 操作系统:Windows NT/2000/XP/2003 编译环境:Visual Studio 6.0 + SP3/SP5/SP6 数据库:可连通的 Oracle 服务器及可用的账号、密码,Connect/Resource 权限,并配置好 Net Config 网络:可连接到 WWW 的网络 下载:http://www.snowywolf.net/MyFolder/Source/adoSourceCode.rar(9K) 并解压到本地硬盘, 解压后是四个文件:ADOConnection.h/ADOConnection.cpp/ADORecordset.h/ADORecordset.cpp http://emag.csdn.net - 29 - 2005 年 1 月 1 期 总第 3 期
  33. 33. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 1.2. 建立 VC 工程 在 D:建立 VCProg 文件夹 打开 Microsoft Visual C++ 6.0 菜单:[File]->[New] Project 选项卡中选择:MFC AppWizard(exe) Location 中输入:D:VCProg Project name 中输入:OraApp (输入的时候可以发现 Location 在同步变化) 点击 OK,弹出 MFC AppWizard - Step1,我们将创建一个基于对话框的应用程序,所以应用 程序类型选择:Dialog based http://emag.csdn.net - 30 - 2005 年 1 月 1 期 总第 3 期
  34. 34. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 其余参数保持默认,直接点[Finish]按键,结束向导。 http://emag.csdn.net - 31 - 2005 年 1 月 1 期 总第 3 期
  35. 35. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 点击 OK 将前面下载并解压的四的文件拷贝到 D:VCProgOraApp 下,文件夹内容如下所示: http://emag.csdn.net - 32 - 2005 年 1 月 1 期 总第 3 期
  36. 36. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 Visual C++ 6.0 中,WorkSpace 视口中选择 FileView 选项卡,在 OraApp Files 节点上右键单击, 弹出的菜单中点击[Add File to project…] http://emag.csdn.net - 33 - 2005 年 1 月 1 期 总第 3 期
  37. 37. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 选择拷贝过来的四个文件添加到当前工程中 http://emag.csdn.net - 34 - 2005 年 1 月 1 期 总第 3 期
  38. 38. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 打开并编辑 StdAfx.h 文件: 添加: #import "C:Program FilesCommon FilesSystemADOmsado15.dll" rename_namespace("MYADO") rename("EOF", "EndOfFile") http://emag.csdn.net - 35 - 2005 年 1 月 1 期 总第 3 期
  39. 39. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 COraApp::InitInstance()函数中 AfxEnableControlContainer();一行下添加如下代码: if(!AfxOleInit()) { AfxMessageBox("OLE 初始化失败!"); return FALSE; } 保存工程:菜单 [File]->[Save All] 按[F7]编译工程,应该没有错误(有一处警告),如果有错误,检查前面的步骤。 按[F5]运行程序,结果如下: http://emag.csdn.net - 36 - 2005 年 1 月 1 期 总第 3 期
  40. 40. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 至此,建立 VC 工程完毕。 1.3. 设计应用程序界面 WorkSpace 视口中选择 Resource View,展开 Dialog 并双击 IDD_ORAAPP_DIALOG http://emag.csdn.net - 37 - 2005 年 1 月 1 期 总第 3 期
  41. 41. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 删除默认的确定和取消按钮,添加如下三个按钮,并将它们的 ID 分别设为 IDC_ADD / IDC_DEL / IDC_SHOW: http://emag.csdn.net - 38 - 2005 年 1 月 1 期 总第 3 期
  42. 42. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 添加四个 Static Text,姓名、电话和 Email 的不需要设置 ID,photo 的 ID 设为 IDC_PHOTO 添加三个 Edit Box,ID 分别设为 IDC_NAME/IDC_TEL/IDC_EMAIL http://emag.csdn.net - 39 - 2005 年 1 月 1 期 总第 3 期
  43. 43. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 还需要两个按钮,ID 分别设为 IDC_CONNECT/IDC_CREATETABLE,添加并调整布局,结 果如下所示: Ctrl+W 调出 MFC ClassWizard,在 Member Variables 选项卡中为以下控件指定 control 类型的 绑定变量: IDC_NAME/IDC_TEL/IDC_EMAIL/IDC_PHOTO,结果如下所示: http://emag.csdn.net - 40 - 2005 年 1 月 1 期 总第 3 期
  44. 44. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 OK,至此,用户界面设计完成。 1.4. 填写代码 在 IDD_ORAAPP_DIALOG 设计窗口中双击[连接]按钮,VC 弹出对话框提示创建响应函数, 保留默认函数名,点击[OK] http://emag.csdn.net - 41 - 2005 年 1 月 1 期 总第 3 期
  45. 45. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 VC 自动转到 OraAppDlg 的代码窗口,光标在 OnConnect()函数中: http://emag.csdn.net - 42 - 2005 年 1 月 1 期 总第 3 期
  46. 46. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 我们先不在这里添加代码,先打开 OraAppDlg.h 文件,添加两个#include 和一个成员变量的 定义: 转回到 OnConnect()函数,添加如下代码: void COraAppDlg::OnConnect() { //此处的连接参数需要根据具体情况进行修改 //参数的顺序为 SID UserName Password m_con.OpenOracle("sunserve","sm5","sm5"); if(m_con.IsConnected()) { AfxMessageBox("已建立到 Oracle 服务器的连接"); } else { AfxMessageBox("建立到 Oracle 服务器的连接失败,请检查连接参数"); } http://emag.csdn.net - 43 - 2005 年 1 月 1 期 总第 3 期
  47. 47. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 } OK,现在可以编译并运行一下程序看一下效果了,按[F5]->是[Yes],应该没有编译错误,弹 出对话框,点连接按钮,如果连接参数正确,会弹出成功建立连接的消息。 转回 DIALOG 设计窗口,双击[建表]按钮,添加响应函数: http://emag.csdn.net - 44 - 2005 年 1 月 1 期 总第 3 期
  48. 48. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 点击 OK,并在 OnCreateTable()函数中添加如下代码: void COraAppDlg::OnCreatetable() { if(!m_con.IsConnected()) { AfxMessageBox("请先点击连接按钮建立到数据库的连接"); return; } CString strSQL; strSQL.Format("Drop table MyFriends"); m_con.Execute(strSQL); strSQL.Format("Create table MyFriends(" "ID int primary key, " "Name varchar2(20)," "Tel varchar2(20)," "Email varchar2(32)," "Photo Blob default empty_blob())"); if(m_con.Execute(strSQL)) { AfxMessageBox("建表成功!"); } else { AfxMessageBox("建表失败!"); } } 按[F5]->是(Y)编译并运行程序,如果直接点建表,会提示需要先连接,点连接按钮建立连接, 点击建表按钮,应该提示建表成功。 下面该添加记录了,很简单: DIALOG 设计视图中双击[添加]按钮并添加默认响应函数,在 OnAdd()函数中添加如下代码: void COraAppDlg::OnAdd() { if(!m_con.IsConnected()) { AfxMessageBox("请先点击连接按钮建立到数据库的连接"); return; } http://emag.csdn.net - 45 - 2005 年 1 月 1 期 总第 3 期
  49. 49. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 CADORecordset rs; //定义 Recordset 对象 rs.SetConnection(&m_con); //为 Recordset 对象设置连接对象 CString strSQL; strSQL.Format("Select * from MyFriends where 1<0"); //构造 SQL 语句 rs.OpenForUpdate(strSQL); //以可更新方式打开 rs.AddNew(); //声明一下要添加记录 rs.SetIntValue(0,1); //ID rs.SetStringValue(1,"SnowyWolf"); //Name rs.SetStringValue(2,"12345678"); //Tel rs.SetStringValue(3,"SnowyWolf@itpub.net"); //Email //======================================================= //{{ by LISJ at [2005-01-26 09:53:40] // * 下面一段很关键,就是很多人都关心的把图片文件写入到 BLOB 字段中 CFile file; file.Open("d:vcproglsj.jpg",CFile::modeRead); //打开图片文件 int nDataLen = file.GetLength(); BYTE * pData = new BYTE[nDataLen]; //开辟内存空间 file.Read(pData,nDataLen); file.Close(); rs.SetBlobValue(4,pData,nDataLen); //这么简单?对!就是这么简单 //}} by LISJ at [2005-01-26 09:53:40] //======================================================= if(rs.Update()) { AfxMessageBox("成功添加记录!"); } else { AfxMessageBox("添加记录失败!"); } delete []pData; //不要忘记释放内存 } 按[F5]->是(Y)编译并运行程序,还是要先点[连接]建立到数据库的连接,点[添加],提示记录 添加成功,此处可以验证一下,在 SQLPlus 中: SQL> select id,name,tel,email,dbms_lob.getlength(photo) from myfriends; ID NAME TEL ---------- -------------------- -------------------- EMAIL DBMS_LOB.GETLENGTH(PHOTO) -------------------------------- ------------------------- http://emag.csdn.net - 46 - 2005 年 1 月 1 期 总第 3 期
  50. 50. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 1 SnowyWolf 12345678 SnowyWolf@itpub.net 44854 删除操作很简单,为[删除]按钮添加默认响应函数,OnDel()函数代码如下: void COraAppDlg::OnDel() { if(!m_con.IsConnected()) { AfxMessageBox("请先点击连接按钮建立到数据库的连接"); return; } CString strSQL; strSQL.Format("truncate table myfriends"); m_con.Execute(strSQL); } 这段代码很简单,就不过多解释了。 下面是最后一个按钮了,也是一个关键部分: 添加[显示]按钮的默认响应函数,OnShow()代码如下: void COraAppDlg::OnShow() { if(!m_con.IsConnected()) { AfxMessageBox("请先点击连接按钮建立到数据库的连接"); return; } int nRecCount = 0; CADORecordset rs; rs.SetConnection(&m_con); //======================================================= //{{ by LISJ at [2005-01-26 10:12:34] // * 检查表中是否有可以显示的记录 CString strSQL; strSQL.Format("Select Count(*) from MyFriends where id>0"); rs.OpenForReadonly(strSQL); rs.GetIntValue(0,nRecCount); if(nRecCount<1) { http://emag.csdn.net - 47 - 2005 年 1 月 1 期 总第 3 期
  51. 51. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 AfxMessageBox("表中没有可以显示的记录,请先添加记录"); rs.Close(); return; } //}} by LISJ at [2005-01-26 10:12:34] //======================================================= CString strName,strTel,strEmail; strSQL.Format("Select * from MyFriends"); rs.OpenForReadonly(strSQL); rs.GetStringValue(1,strName); rs.GetStringValue("Tel",strTel); rs.GetStringValue("Email",strEmail); //======================================================= //{{ by LISJ at [2005-01-26 10:15:07] // * 读取 BLOB 字段的数据,也不麻烦,是吧 BYTE * pData = NULL; int nLenth = 0; rs.GetBlobValue(4,pData,nLenth); //}} by LISJ at [2005-01-26 10:15:07] //======================================================= rs.Close(); //======================================================= //{{ by LISJ at [2005-01-26 10:30:48] // * 显示姓名、电话和 Email m_editName.SetWindowText(LPCTSTR(strName)); m_editTel.SetWindowText(LPCTSTR(strTel)); m_editEmail.SetWindowText(LPCTSTR(strEmail)); //}} by LISJ at [2005-01-26 10:30:48] //======================================================= //======================================================= //{{ by LISJ at [2005-01-26 10:15:45] // * 下面这段代码比较麻烦,是要显示图片 CDC *pDC = m_picPhoto.GetDC(); IStream *pStm; HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, nLenth); http://emag.csdn.net - 48 - 2005 年 1 月 1 期 总第 3 期
  52. 52. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 LPVOID pvData = NULL; if (hGlobal != NULL) { if ((pvData = GlobalLock(hGlobal)) != NULL) { memcpy(pvData,pData,nLenth); GlobalUnlock(hGlobal); CreateStreamOnHGlobal(hGlobal, TRUE, &pStm); } } IPicture *pPic; if(SUCCEEDED(OleLoadPicture(pStm,nLenth,TRUE,IID_IPicture,(LPVOID*)&pPic)) ) { OLE_XSIZE_HIMETRIC hmWidth; OLE_YSIZE_HIMETRIC hmHeight; pPic->get_Width(&hmWidth); pPic->get_Height(&hmHeight); double fX,fY; fX = (double)pDC->GetDeviceCaps(HORZRES)*(double)hmWidth/((double)pDC->GetDeviceCaps(HO RZSIZE)*100.0); fY = (double)pDC->GetDeviceCaps(VERTRES)*(double)hmHeight/((double)pDC->GetDeviceCaps(V ERTSIZE)*100.0); if(FAILED(pPic->Render(*pDC,0,0,(DWORD)fX,(DWORD)fY,0,hmHeight,hmWidth,-hmHeig ht,NULL))) AfxMessageBox("显示图片失败!"); pPic->Release(); } else { AfxMessageBox("装载图像失败!"); } //}} by LISJ at [2005-01-26 10:15:45] //======================================================= delete []pData; } 很精彩的一段代码,Isn’t it? http://emag.csdn.net - 49 - 2005 年 1 月 1 期 总第 3 期
  53. 53. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 调整一下 Dialog 的布局,[F5]编译并运行,最终效果如下所示: 1.5. 小结一下 至此,VC+ADO 实现 Oracle 客户端应用程序的 DEMO 就全部完成了,您会发现这个应用程 序有很多不足之处: 没有处理错误消息 只能处理一条记录,不能前后移动游标 不能对当前记录进行修改 …… 但它毕竟只是一个 DEMO,时间、篇幅的限制加上雪狼水平有限,还不能把它做得很完美。 但至少我们建立了一个能完成基本功能的 Oracle 应用程序,通过雪狼封装并对您提供的两个 类,您可以方便地进行如下操作: 建立/断开与数据库的连接 执行 SQL 语句 开始/提交/回滚事务 查询结果集并获取数据 http://emag.csdn.net - 50 - 2005 年 1 月 1 期 总第 3 期
  54. 54. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 添加、修改记录 游标的自由移动 …… 1.6. 两个封装类的说明 下面对两个封装类的方法作简要的说明,更详细的说明请直接查看源代码。 1.6.1. CADOConnection 数据连接类,建立/断开与数据库的连接,执行 SQL 语句 方法说明: 方法 简要说明 OpenOracle 建立与 Oracle 数据库服务器的连接 IsConnected 判断是否已连接 Close 关闭连接 Execute 执行 SQL 语句 BeginTrans 开始事务 CommitTrans 提交事务 Rollback 回滚事务 CheckError 处理错误信息 1.6.2. CADORecordset 记录集类,处理查询结果集。 方法说明: 方法 简要说明 SetConnection 设置连接对象的指针 SetSQL 设置查询 SQL 语句 OpenForReadonly 以只读方式打开 OpenForUpdate 以可更新方式打开 http://emag.csdn.net - 51 - 2005 年 1 月 1 期 总第 3 期
  55. 55. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 IsOpen 判断记录集是否已打开 CanUpdate 判断是否要执行更新操作 IsBOF 是否到记录集头 IsEOF 是否到记录集尾 IsEmpty 记录集是否为空 MoveFirst 移到第一条记录 MovePrev 移到前一条记录 MoveNext 移到后一条记录 MoveLast 移到最后一条记录 GetFieldName 指定序号获取字段的名字 GetFieldType 指定序号或名字获取字段的类型 GetFieldCount 获取字段的数目 GetIntValue GetDoubleValue 获取指定字段的值 GetStringValue GetBlobValue SetIntValue SetDoubleValue 设置指定字段的值 SetStringValue SetBlobValue AddNew 添加新的记录 Update 提交更新操作 1.7. 后续工作 CADORecordset 类还需要完善,如添加 FindFrist/FindPrev/FindNext/FindLast 方法。 添加 CADOCommand 类,可以用来处理带参数的存储过程 增加对其他数据类型的读写,如时间类型等 http://emag.csdn.net - 52 - 2005 年 1 月 1 期 总第 3 期
  56. 56. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 1.8. 完整源代码下载 http://www.snowywolf.net/MyFolder/Source/vcprog.rar 作者简介: 照片 姓名:李绍俊 暂缺 网名:SnowyWolf CSDN eMag Oracle 电子杂志主编 现任 itpub Oracle 电子文档版版主. 作品展示: Oracle 9i/10g 部分在线文档(chm 版) http://www.snowywolf.net/chm.htm Ask Tom 历年问题合订本(chm 版) http://www.snowywolf.net/chm.htm DBA 小工具 OraExplore http://www.snowywolf.net/OraExplore/index.htm 个人主页:http://www.snowywolf.net E-mail:SnowyWolf@itpub.net Lisj@SuperMap.com http://emag.csdn.net - 53 - 2005 年 1 月 1 期 总第 3 期
  57. 57. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 数据库探秘 深入了解 Oracle 数据字典 ——深入了解 Oracle 数据字典,提高自学习 Oracle 能力 本文作者: eygle (eygle.com@gmail.com ) 摘要:我们知道 Oracle 通过数据字典来管理和展现数据库信息,这些信息至关重要。正确理 解这部分内容有助于加强我们的 oracle 学习能力。 本文对 Oracle 数据字典的关系进行探讨。 接下来我们介绍一下怎样通过数据库本身来学习研究数据库。 首先,Oracle 的字典表和视图基本上可以分为三个层次。 1.1. X$表 这一部分表是 Oracle 数据库的运行基础,在数据库启动时由 Oracle 应用程序动态创建。 这部分表对数据库来说至关重要,所以 Oracle 不允许 SYSDBA 之外的用户直接访问,显式授权不 被允许。 如果显式授权你会收到如下错误: SQL> grant select on x$ksppi to eygle; grant select on x$ksppi to eygle * ERROR at line 1: ORA-02030: can only select from fixed tables/views 1.2. GV$和 V$视图 从 Oracle8 开始,GV$视图开始被引入,其含义为 Global V$. 除了一些特例以外,每个 V$视图都有一个对应的 GV$视图存在。 http://emag.csdn.net - 54 - 2005 年 1 月 1 期 总第 3 期
  58. 58. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 GV$视图的产生是为了满足 OPS 环境的需要,在 OPS 环境中,查询 GV$视图返回所有实例信 息,而每个 V$视图基于 GV$视图,增加了 INST_ID 列判断后建立,只包含当前连接实例信息。 注意,每个 V$视图都包含类似语句: where inst_id = USERENV('Instance') 用于限制返回当前实例信息。 我们从 GV$FIXED_TABLE 和 V$FIXED_TABLE 开始 SQL> select view_definition from v_$fixed_view_definition where view_name='V$FIXED_TABLE'; VIEW_DEFINITION ------------------------------------------------------------------------------ select NAME , OBJECT_ID , TYPE , TABLE_NUM from GV$FIXED_TABLE where inst_id = USERENV('Instance') 这里我们看到 V$FIXED_TABLE 基于 GV$FIXED_TABLE 创建。 SQL> select view_definition from v_$fixed_view_definition where view_name='GV$FIXED_TABLE'; VIEW_DEFINITION ------------------------------------------------------------------------------ select inst_id,kqftanam, kqftaobj, 'TABLE', indx from x$kqfta union all select inst_id,kqfvinam, kqfviobj, 'VIEW', 65537 from x$kqfvi union all select inst_id,kqfdtnam, kqfdtobj, 'TABLE', 65537 from x$kqfdt 这样我们找到了 GV$FIXED_TABLE 视图的创建语句,该视图基于 X$表创建。 1.3. GV_$,V_$视图和 V$,GV$同义词 这些视图是通过 catalog.ql 创建。 当 catalog.sql 运行时: create or replace view v_$fixed_table as select * from v$fixed_table; create or replace public synonym v$fixed_table for v_$fixed_table; create or replace view gv_$fixed_table as select * from gv$fixed_table; create or replace public synonym gv$fixed_table for gv_$fixed_table; 我们注意到,第一个视图 V_$和 GV_$首先被创建,v_$和 gv_$两个视图。 http://emag.csdn.net - 55 - 2005 年 1 月 1 期 总第 3 期
  59. 59. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 然后基于 V_$视图的同义词被创建。 所以,实际上通常我们访问的 V$视图,其实是指向 V_$视图的同义词。 而 V_$视图是基于真正的 V$视图(这个视图是基于 X$表建立的)。 而 v$fixed_view_definition 视图是我们研究 Oracle 对象关系的一个入口,仔细理解 Oracle 的数 据字典机制,有助于深入了解和学习 Oracle 数据库知识。 1.4. 再进一步 1.4.1. X$表 关于 X$表,其创建信息我们也可以从数据字典中一窥究竟。 首先我们考察 bootstrap$表,该表中记录了数据库启动的基本及驱动信息。 SQL> select * from bootstrap$; LINE# OBJ# SQL_TEXT ------------------------------------------------------------------------------ -1 -1 8.0.0.0.0 0 0 CREATE ROLLBACK SEGMENT SYSTEM STORAGE ( INITIAL 112K NEXT 1024K MINEXTENTS 1 M 8 8 CREATE CLUSTER C_FILE#_BLOCK#("TS#" NUMBER,"SEGFILE#" NUMBER,"SEGBLOCK#" NUMBER) 9 9 CREATE INDEX I_FILE#_BLOCK# ON CLUSTER C_FILE#_BLOCK# PCTFREE 10 INITRANS 2 MAXT 14 14 CREATE TABLE SEG$("FILE#" NUMBER NOT NULL,"BLOCK#" NUMBER NOT NULL,"TYPE#" NUMBE 5 5 CREATE TABLE CLU$("OBJ#" NUMBER NOT NULL,"DATAOBJ#" NUMBER,"TS#" NUMBER NOT NULL 6 6 CREATE CLUSTER C_TS#("TS#" NUMBER) PCTFREE 10 PCTUSED 40 INITRANS 2 MAXTRANS 255 7 7 CREATE INDEX I_TS# ON CLUSTER C_TS# PCTFREE 10 INITRANS 2 MAXTRANS 255 STORAGE ( .... 这部分信息,在数据库启动时最先被加载,跟踪数据库的启动过程,我们发现数据库启动的 第一个动作就是: create table bootstrap$ ( line# number not null, obj# number not null, sql_text varchar2(4000) not null) storage (initial 50K objno 56 extents (file 1 block 377)) http://emag.csdn.net - 56 - 2005 年 1 月 1 期 总第 3 期
  60. 60. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 这部分代码是写在 Oracle 应用程序中的,在内存中创建了 bootstrap$以后,Oracle 就可以从 file 1,block 377 上读取其他信息,创建重要的数据库对象。从而根据这一部分信息启动数据库,这就 实现了数据库的引导,类似于操作系统的初始化。 这部分你可以参考 biti_rainy 的文章。 X$表由此建立。这一部分表可以从 v$fixed_table 中查到: SQL> select count(*) from v$fixed_table where name like 'X$%'; COUNT(*) ---------- 394 共有 394 个 X$对象被记录。 1.4.2. GV$和 V$视图 X$表建立以后,基于 X$表的 GV$和 V$视图得以创建。 这部分视图我们也可以通过查询 V$FIXED_TABLE 得到。 SQL> select count(*) from v$fixed_table where name like 'GV$%'; COUNT(*) ---------- 259 这一部分共 259 个对象。 SQL> select count(*) from v$fixed_table where name like 'V$%'; COUNT(*) ---------- 259 同样是 259 个对象。 v$fixed_table 共记录了: 394 + 259 + 259 共 912 个对象。 我们通过 V$PARAMETER 视图来追踪一下数据库的架构: SQL> select view_definition from v$fixed_view_definition a where a.VIEW_NAME='V$PARAMETER'; VIEW_DEFINITION ------------------------------------------------------------------------------ http://emag.csdn.net - 57 - 2005 年 1 月 1 期 总第 3 期
  61. 61. 《CSDN 社区电子杂志——MS-SQL Server 杂志》 select NUM , NAME , TYPE , VALUE , ISDEFAULT , ISSES_MODIFIABLE , ISSYS_MODIFIA BLE , ISMODIFIED , ISADJUSTED , DESCRIPTION, UPDATE_COMMENT from GV$PARAMETER wh ere inst_id = USERENV('Instance') 我们看到 V$PARAMETER 是由 GV$PARAMETER 创建的。 SQL> select view_definition from v$fixed_view_definition a where a.VIEW_NAME='GV$PARAMETER'; VIEW_DEFINITION ----------------------------------------------------------------------------- select x.inst_id,x.indx+1,ksppinm,ksppity,ksppstvl,ksppstdf, decode(bitand(kspp iflg/256,1),1,'TRUE','FALSE'), decode(bitand(ksppiflg/65536,3),1,'IMMEDIATE',2, 'DEFERRED', 3,'IMMEDIATE','FALSE'), decode(bit and(ksppstvf,7),1,'MODIFIED',4,'SYSTEM_MOD','FALSE'), decode(bitand(ksppstvf,2) ,2,'TRUE','FALSE'), ksppdesc, ksppstcmnt from x$ksppi x, x$ksppcv y where (x.i ndx = y.indx) and ((translate(ksppinm,'_','#') not like '#%') or (ksppstdf = 'F ALSE')) 在这里我们看到 GV$PARAMETER 来源于 x$ksppi,x$ksppcv 两个 X$表。x$ksppi,x$ksppcv 基 本上包含所有数据库可调整参数,v$parameter 展现的是不包含"_"开头的参数。以"_"开头的参数我 们通常称为隐含参数,一般不建议修改,但很多因为功能强大经常使用而广为人知。 http://emag.csdn.net - 58 - 2005 年 1 月 1 期 总第 3 期

×