检测方法优化变更条件怎么走java程序性能优化 pdf

用于动态优化的程序阶段检测的制作方法
专利名称用于动态优化的程序阶段检测的制作方法
用于动态优化的程序阶段检测技术领域本实施例涉及可管理的运行时计算机系统环境技术,更具体地, 涉及通过阶段检测进行的动态优化。
背景技术设计成运行于可管理的运ft时环境(MRTE)的计算机程序是以中 性字节码的格式分发的,且这些程序必须由动态编译器编译成本地机 器码。受到管理的应用程序的性能取决于由编译器执行的优化和代码 生成的质量。可将系统利用率监视用于确定何时需要优化各种应用程 序。随着运行在系统上的应用程序的数量的增加,对应用程序优化的 需要也随之增加了。许多微处理器结构依赖于编译器的性能优化。某些结构的性能非 常依赖于昂贵和复杂的代码生成优化(如全局调度和控制预测)。为优化可执行代码,使用了性能反馈和优化技术。这些技术的问 题是,它们通常通过硬件实施或是专用的,因此并不适于动态优化或 软件实施。而且,许多优化要求等待-观察的方法,因为要试验不同 的优化标准来实现优化。这个过程相当耗时,而且由于系统利用的变 化,可能仅能在短时间内优化应用程序。
在附图的各幅图中,通过举例而非限制的方式说明了本发明的实 施例,其中,相似的附图标记指示相似的组件。应当注意,在本公开 中,本发明的"某一"实施例不一定指相同的实施例,且它们意味着 至少一个实施例。
图1示出了用于检测稳定的程序阶段(phase)的进程(process)的 一个实施例。
图2示出了分支跟踪緩冲区(BTrB)的样本地址随时间的实例緩 冲区的图。
图3示出了对应于两个已检测阶段的直方图。
图4示出了使用图2中的数据时检测到的阶段序列。
图5示出了一个系统的实施例。
图6示出了与另一系统耦合的系统的实施例。
具体实施例方式
本文讨论的实施例通常涉及一种用于动态检测稳定进程阶段的 方法和系统。参考附图,下面将描述一些示范实施例。这些示范实施 例用于说明实施例,且不应当将它们视为对实施例范围的限制。
具有动态档案导引优化(例如可管理的运行时环境、动态二进 制优化器、以及动态二进制翻译器)的系统试图确定何时动态地重新 优化正在执行的程序。图1示出了用于可执行代码的动态优化的、检 测稳定程序阶段的进程的一个实施例。在框110处,进程100以选择 阶段阈值开始。该阶段阈值可以是在时间t采集的分支地址的M个 连续样本的函数。在一个实施例中,用户选择上述阶段阈值,并将该 值作为进程中的预定静态参数输入。也可通过用户输入装置动态修改 阶段阈值。
进程100继续进行到框120。在框120中,接收多个经过排序的 緩冲区(buffer)。在一个实施例中,性能监视单元(PMU)收集经过排序 的分支跟踪緩冲区(BTrB)。可以将这些经过排序的緩冲区存储在本地 存储器或文件中。所接收的緩冲区包括所取得的最后L个分支的地 址。L的值可以是预定的或是由用户选定(如4、 8、 10等)。所取得的 分支地址的緩冲区对应于特定的采样时刻。图2示出了在执行诸如基 准程序的实例程序期间,BTrB才羊本地址的实例緩冲区随时间的图。在框120完成后,进程100继续进行到框130。框130确定在至 少两个连续直方图区间的中心之间的距离。在一个实施例中,分支地 址的向量如下确定bt=(bt,lv..ba)T,它代表在时间t的单个BTrB样本 的分支地址的向量。Bt-bt,bw,...btM是某一时刻可用的M个连续样本 的緩冲区。M是预定的或由用户动态调整,如1000、 1400、 1820, 等等。稳定阶段定义为Bt的一维直方图,并被标注为H产[ht,i,...ht,w;T。 直方图Ht是大小为N的向量,其中N是直方图区间的总数。Wlv..WN 是一组间隔相等且非重叠的直方图区间,它们覆盖了可能分支地址的 整个空间。AW-Wk-Wk,,是两个连续直方图区间的中心之间的距离。 在一个实施例中,用欧几里得3巨离计算方法来测量距离,即距离(Hk,(V,-hLi)2,5。应当注意,在不偏离本实施例范围情况下,也可以使用本技术领域已知的其他距离算法。在框130完成之后,框140将所确定的距离与阶段阈值进行比 较。如果两个连续直方图区间之间的距离等于或大于阶段阈值,则Bk 与B,中的样本属于不同的阶段,否则这些样本属于相同的阶段。因 此,根据比较的结果确定可执4亍进程的主执行阶段。在框140完成之后,如果Bk与B,中的样本属于相同阶段,则进 程IOO继续进行到框150。在一个实施例中,设置指示相同阶段的变 量。如果Bk与B,中的样本属于不同阶段,则在一个实施例中,框145 设置指示不同阶段的变量。在一个实施例中,框160发送信号,以便 重新优化正在执行的进程。可将该信号发送到例如动态编译器。应当注意,增加直方图区间的距离宽度AW会粗化分辨率,并 会减少阶段检测进程100的复杂度。粗分辨率用于阶段检测,而细分 辨率用于热跟踪检测。设置AW—,便将每个单个的分支地址放置在 不同的直方图区间中。这样,便创建了细粒度直方图。创建细粒度直 方图的结果是,减慢了阶段检测进程100,且可能增加阶段的数量。
设置△ W&& 1 ,便将相同存储区中的分支地址放置在相同的直方图区 间中。这样的结果是创建了粗粒度直方图。创建粗粒直方图加速了阶段检测进程100,并减少了阶段的数量。通过改变AW,可以对不同 分辨率的直方图作出分析。因而,可实现阶段检测开销和阶段检测精 度之间的动态折中。在一个实施例中,进程100的主执行阶段的确定 是以预定周期速度执行的动态进程。例如,可用选定的速度(如每5 分钟、每小时、每24小时等)执行进程100。在另一个实施例中,进 程100是人工执行的,因为它是由用户选择的。为了举例,图2示出在实例程序执行期间BTrB样本地址的实例 緩沖区随时间的图表具有以下设置L=4,M=1820,AW=105,且阶段 阈值-0.4M。图3示出了对应于两个已检测阶段的直方图,而图4示 出了使用图2中的数据时所检测的阶段序列(对37个数据块而言)。可以在采用动态档案导引优化(如MRTE、动态二进制优化器和 动态二进制翻译器)的系统中应用进程100。这类系统包含硬件性能监 视,且它们的性能依赖于档案导引优化。图5示出了一个系统的实施例。系统500包括连接到存储器520 的处理器510。在一个实施例中,存储器520是诸如随机存取存储器 (RAM)、静态随机存取存储器(SRAM)、动态随机存取存储器 (DRAM)、同步DRAM(SDRAM)、只读存储器(ROM)之类的主存储 器。在另一个实施例中,存储器520是高速緩冲存储器。进程100采 用运行在处理器510中并与存储器520进行通信的可执行进程的形 式。在该实施例中,进程IOO是阶段检测器进程,该阶段检测器进程 确定运行在存储器520中的另一个可执行进程的主执行阶段。在系统 500中,进程100确定何时对运行在系统500中的另一可执行进程进 行重新优化。根据应用场合,可以将系统500与其他已知的组件进行 组合。例如,如果将系统500用于多处理器系统中,则可将其它多处 理器系统的典型的已知组件与系统500进行耦合。系统500可用于多种应用场合,如个人计算机(PC)、个人数字助理(PDA)、笔记本计算 机、服务器、MRTE、动态二进制优化器、动态二进制翻译器等。在 一个实施例中,阶段#:测器进程100作为硬件单元存在,且该硬件单 元具有逻辑电路和用以接收緩冲区的接收器。如上所述,该阶段检测 器的逻辑组件包括用于执行进程100所执行的指令的电路。图6示出了耦合到系统650的系统600。系统600包括至少一个 处理器610、编译器620和存储器640。根据应用场合,系统600也 包括其它诸如多处理器系统、PC、 PDA等的典型系统的组件。编译 器620是动态编译器。系统650包括处理器670、存储器680和编译 器660。在一个实施例中,编译器620和660是动态编译器。在一个 实施例中,进程100采用运行在系统600或650中的可执行进程的形 式。在本实施例中,进程IOO是阶段检测器进程,该阶段检测器进程 确定在系统600和/或650中运行的另一个可执行进程的主执行阶 段。也就是说,进程100可以在系统600中运行,以检测系统650中 的主执行阶段,和/或进程100可以在系统650中运行,以检测系统 600中的主执行阶段。系统600和650可以同处一地,可以是分布式 系统或联网的系统。在一个实施例中,存储器640和存储器680均可 以是主存储器(例如随机存取存储器(RAM)、静态随机存取存储器 (SRAM)、动态随机存取存储器(DRAM)、同步DRAM(SDRAM)、只 读存储器(ROM)等)或高速緩沖存储器。在一个实施例中,阶段检测 器是具有逻辑电路和用于接收緩冲区的接收器的硬件单元。如上所 述,上述阶段检测器的逻辑组件包括用于执行进程100所执行的指令 的电路。也可将以上实施例存储在装置或机器可读介质上,并通过机器读 取来执行指令。机器可读介质包括提供(即存储和/或传送)以机器(例 如计算机)可读形式的信息的任何机构。例如,机器可读介质包括只 读存储器(ROM),随机存取存储器(RAM),磁盘存储介质,光存储介
质,闪存装置,生物电路、机械系统,电、光、声或其它形式的传播 信号(例如,载波、红外信号、凄丈字信号等)。上述装置或机器可读介 质可包括微机电系统(MEMS)、纳米技术装置、有机物装置、全息装 置、固态存储装置和/或旋转磁盘或光盘。当指令的各个部分已分别 保存在不同的机器中(如分别保存在相互连接的计算机中)时,可将装 置或机器可读介质分布设置。
尽管已描述了 一些特定的示范实施例,并在附图中示出了这些实 施例,但是,仍应当理解,这些实施例仅仅是对本发明的解释,而不 对其构成限制,并且本发明不限于所示和所述的特定结构和配置,因 为对本领域的普通技术人员而言,可以对上述实施例进行各种其他的 修改。
1. 一种方法,包括 选择阶段阈值,接收多个经过排序的緩冲区,确定在至少两个连续直方图区间的中心之间的距离, 将所述距离与所述选择的阈值进行比较,以及 根椐所述比较来确定可执行进程的主执行阶段。
2. 如权利要求1所述的方法,所述多个经过排序的援沖区包括 多个样本,所述样本包含在某一采样时间取得的多个分支的地址。
3. 如权利要求1所述的方法,还包括 确定代表分支跟踪緩冲区的多个分支地址, 确定代表所述分支跟踪緩冲区的多个连续分支地址, 为所述多个连续分支地址确定稳定阶段直方图,以及为所有可能的分支地址确定多个间隔相等且非重叠的直方图区间。
4. 如权利要求1所述的方法,其中所述确定主执行阶段的结果 发信号要求动态编译可执行代码,以便优化所述可执行代码。
5. 如权利要求l所述的方法,还包括确定所述至少两个连续直方图区间是否处于相同的阶段。
6. 如权利要求5所述的方法,如果所述距离比等于和小于所述 选择的阶段阈值其中之一要小,则所述至少两个连续直方图处于相同 阶段。
7. —种包括机器可读介质的设备,所述机器可读介质包含指 令,当机器执行所述指令时,使得所述机器执行以下操作选择阶段阈值,接收多个经过排序的緩沖区,确定代表分支跟踪緩沖区的多个分支地址, 确定在至少两个连续直方图区间的中心之间的距离,其中所述至 少两个直方图区间是非重叠的,以及将所述距离与所述选择的阈值进行比较。
8. 如权利要求7所述的设备,还包括指令,当机器执行所述指 令时,使得所述机器执行以下操作确定代表所述分支跟踪緩冲区的多个连续分支地址, 为所述多个连续分支地址确定稳定阶段直方图, 为所有可能的分支地址确定多个间隔相等且非重叠的直方图区 间,以及根据所述比较确定可执行进程的主执行阶段。
9. 如权利要求8所述的设备,其中所述确定主执行阶段以预定 的周期速度动态变化。
10. 如权利要求8所述的设备,其中所述确定主执行阶段是以人 工方式开始的。
11. 如权利要求7所述的设备,所述多个经过排序的緩冲区包括 多个样本,所述样本包含在某一采样时间取得的多个分支的地址。
12. 如权利要求7所述的设备,其中所述确定主执行阶段的指令 的结果发信号要求动态编译可执行代码,以便优化所述可执行代码。
13. 如权利要求7所述的设备,还包括指令,当机器执行所述指 令时,使得所述机器执行以下操作确定所述至少两个连续直方图区间是否处于相同的阶段。
14. 如权利要求13所述的设备,如果所述距离比等于和小于所 述选择的阶段阈值的其中之一小,则所述至少两个连续直方图处于相 同阶段。
15. —种系统,包括耦合到主存储器和高速緩冲存储器其中之一的处理器,与所述存储器通信的至少一个进程,以及确定所述至少 一个进程的主执行阶段的阶段检测器。
16. 如权利要求15所述的系统,所述确定的主执行阶段用于确定何时重新优化所述进程。
17. 如权利要求15所述的系统,所述阶段检测器包括用于接收 多个经过排序的緩冲区的接收器,其中所述阶段检测器用于确定代表分支跟踪緩沖区的多个分支 地址,确定在至少两个连续直方图区间的中心之间的距离,其中所述至 少两个直方图区间是非重叠的,以及 将所述距离与预定的阈值进行比较。
18. 如权利要求17所述的系统,所述阶段检测器具有逻辑电路, 用来确定代表所述分支跟踪緩冲区的多个连续分支地址, 为所述多个连续分支地址确定稳定阶段直方图,以及为所有可能的分支地址确定多个间隔相等且非重叠的直方图区间。
19. 如权利要求15所述的系统,其中所述阶段检测器具有以预 定的周期速度动态地确定主执《亍阶段的逻辑电路。
20. 如权利要求17所述的系统,所述多个经过排序的緩冲区包 括多个样本,所述样本包含在某一采样时间取得的多个分支的地址。
21. —种系统,包括第一装置,具有耦合到第一存储器的第一处理器和至少一个与所 述第一存储器通信的进程,以及第二装置,具有耦合到第二存储器的第二处理器和至少另 一个与 所述第二存储器通信的进程,其中阶段检测器进程在所述第一处理器和所述第二处理器其中 之一中工作,以便确定所述第一装置和所述第二装置其中之一内的所 述一个进程和所述另一个进程其中之一的主执行阶段。
22. 如权利要求21所述的系统,所述主执行阶段用于确定何时 重新优化所述一个进程和所述另 一个进程。
23. 如权利要求21所述的系统,所述阶段检测器具有逻辑电路, 用来接收多个经过排序的緩冲区, 确定代表分支跟踪緩冲区的多个分支地址, 确定在至少两个连续直方图区间的中心之间的距离,其中所述至 少两个直方图区间是非重叠的,以及 将所述距离与预定的阈值进行比较。
24. 如权利要求23所述的系统,所述阶段检测器具有逻辑电路, 用来确定代表所述分支跟踪緩冲区的多个连续分支地址,为所述多个连续分支地址确定稳定阶段直方图,以及为所有可能的分支地址确定多个间隔相等且非重叠的直方图区间。
25. 如权利要求21所述的系统,其中所述阶段检测器具有以预 定的周期速度动态确定主执行阶段的逻辑电路。
26. 如权利要求23所述的系统,所述多个经过排序的緩冲区包 括多个样本,所述样本包含在某一采样时间取得的多个分支的地址。
一种方法、装置和系统,包括选择阶段阈值,接收多个经过排序的缓冲区,确定至少两个连续直方图区间的中心之间的距离,将该距离与选定的阈值进行比较,并根据该比较确定可执行进程的主执行阶段。
文档编号G06F9/45GKSQ
公开日日 申请日期日 优先权日日
发明者A·-R·阿德尔-塔巴塔拜, A·V·内费安 申请人:英特尔公司PLSQL程序优化和性能测试方法
PLSQL程序优化和性能测试方法
性能测试是测试中比较重要的工作,性能测试应分为压力的测试和性能的测试,其中性能问题中绝大部分都是由于程序编写的不合理、不规范造成的。本文档说明了程序中常见的不优化的脚本编写,导致的性能问题,并且在也描述了怎样去跟踪和解决程序上的性能问题的方法。
在最后一章里面描述了做一个白盒测试工具测试性能问题的设计思想。
本文档只说明PLSQL编写的优化问题,不包括ORACLE本身的性能优化(内存SGA、系统参数、表空间等)、操作系统的性能问题和硬件的性能问题。对于PLSQL程序优化方面的内容有很多,本文档列出在我们实际工作中一些常见的情况。本文档难免有不正确的地方,也需要大家给予指正。
本文档举例说明的问题语句不是实际程序中真正存在的,只是让大家能看起来更容易理解,但这些语句也不代表在我们程序中其他部分语句不存在这些问题。
举例说明中的语句采用的是社保核心平台的数据字典,在举例描述中没有标明表名和字段名的含义,还需单独参考。
1.4 参考资料
程序优化原则
导致系统性能出现问题从系统底层分析也就是如下几个原因:
CPU占用率过高,资源争用导致等待
内存使用率过高,内存不足需要磁盘虚拟内存
IO占用率过高,磁盘访问需要等待
优化的核心思想
PLSQL优化实际上就是避免出现“导致性能问题的内在原因”,实际上编写程序,以及性能问题跟踪应该本着这个核心思想去考虑和解决问题。
PLSQL程序占用CPU的情况
系统解析SQL语句执行,会消耗CPU的使用
运算(计算)会消耗CPU的使用
PLSQL程序占用内存的情况
读写数据都需要访问内存
内存不足时,也会使用磁盘
PLSQL程序增大IO的情况
读写数据都需要访问磁盘IO
读取的数据越多,IO就越大
性能的优先级CPU-&内存-&IO,影响性能的因素依次递增。根据上面的分析,PLSQL优化的核心思想为:
避免过多复杂的SQL脚本,减少系统的解析过程
避免过多的无用的计算,例如:死循环
避免浪费内存空间没有必要的SQL脚本,导致内存不足
内存中计算和访问速度很快
尽可能的减少磁盘的访问的数据量,该原则是PLSQL优化中重要思想。
尽可能的减少磁盘的访问的次数,该原则是PLSQL优化中重要思想。
下面的章节具体介绍常见影响性能的SQL语句情况。
主要说明了在SQL编写上和PLSQL程序编写上可以优化的地方。
子句中的连接顺序
ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前
SELECT ab01.aab001,ab02.aab051
&FROM ab01,ab02
WHERE ab02.aae140=’31’
ab01.aab001=ab02.aab001;
SELECT ab01.aab001,ab02.aab051
&FROM ab01,ab02
WHERE ab01.aab001=ab02.aab001
ab02.aae140=’31’;
子句中避免使用 ‘ *
当你想在SELECT子句中列出所有的COLUMN时,使用动态SQL列引用 ‘*'
是一个方便的方法.不幸的是,这是一个非常低效的方法. 实际上,ORACLE在解析的过程中,
依次转换成所有的列名, 这个工作是通过查询数据字典完成的, 这意味着将耗费更多的时间。
实际情况看,使用exists替换in效果不是很明显,基本一样。
在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行联接.在这种情况下,
使用EXISTS(或NOT
EXISTS)通常将提高查询的效率.
&FROM ac01
Where aac001 in (select aac001 from ac02 where
aab001=str_aab001 and aae140=’31’);
&FROM ac01
Where aac001 in (select distinct aac001 from ac02
where aab001=str_aab001 and aae140=’31’);
注意使用distinct也会影响速度
&FROM ac01
Where exists (select 1 from ac02 where
aac001=ac01.aac001 and aab001=str_aab001 and
aae140=’31’);
in的常量列表是优化的(例如:aab019 in (‘20’,’30’)),不用exists替换;in列表相当于or
EXISTS替代NOT IN
Oracle在10g之前版本not
in都是最低效的语句,虽然在10g上not
in做到了一些改进,但仍然还是存在一些问题,因此我们一定要使用not exists来替代not
in的写法。
在子查询中,NOT
IN子句将执行一个内部的排序和合并. 无论在哪种情况下,NOT
IN都是最低效的 (因为它对子查询中的表执行了一个全表遍历). 为了避免使用NOT IN
,我们可以把它改写成NOT EXISTS.
&FROM ac01
WHERE aab001 NOT IN (SELECT aab001 from ab01 where
aab020=’100’);
为了提高效率.改写为:
&FROM ac01
WHERE not exists (SELECT 1 from ab01 where aab001=ac01.aab001 and
aab020=’100’);
在子查询的表和主表查询是多对一的情况,一般采用表连接的方式比EXISTS更有效率。
SELECT ac01.*
&FROM ac01
Where exists (select 1 from ac02
&&&&&&&&&&&&&&&&&&&&&
where aac001=ac01.aac001
&&&&&&&&&&&&&&&&&&&&&&&
and aab001=ac01.aab001
&&&&&&&&&&&&&&&&&&&&&&&
and aae140='31'
&&&&&&&&&&&&&&&&&&&&&&&
and aae041='200801');
SELECT ac01.*
&FROM ac02,ac01
Where ac02.aac001=ac01.aac001
& and ac02.aab001=ac01.aab001
& and ac02.aae140='31'
& and aae041='200801';
到底exists和表关联哪种效率高,其实是根据两个表之间的数据量差别大小是有关的,如果差别不大实际上速度基本差不多。
EXISTS替换DISTINCT
当提交一个包含一对多表信息(比如个人基本信息表和个人参保信息表)的查询时,避免在SELECT子句中使用DISTINCT.
一般可以考虑用EXISTS替换
select distinct ac01.aac001
from ac02,ac01
where ac02.aac001 = ac01.aac001
and ac02.aae140='31'
and ac01.aab001='100100';
select ac01.aac001
where exists(select 1 from ac02 where aac001 = ac01.aac001
and aae140='31')
and ac01.aab001='100100';
使查询更为迅速,因为RDBMS核心模块将在子查询的条件一旦满足后,立刻返回结果。因此如果不是特别研究和追求速度的话(例如:数据转换),查询一个表的数据需要关联其他表的这种情况查询,建议采用EXISTS的方式。
该问题是我们编程中出现过的问题,请大家一定注意,并且该类问题优化可以带来较大性能的提升。
cursor cur_kc24_mz is
Select akc260
where akb020
=str_akb020
aka130=’11’;&
cursor cur_kc24_zy is
Select akc260
where akb020
=str_akb020
and aka130=’21’;
for rec_mz in cur_kc24_mz loop
门诊处理…..
for rec_mz in cur_kc24_zy loop
住院处理…..
cursor cur_kc24 is
Select akc260,aka130
where akb020
=str_akb020
and aka130 in (’11’,’21’);
for rec_kc24 in cur_kc24 loop
rec_kc24.aka130=’11’ then
门诊处理…..
rec_kc24.aka130=’21’ then
住院处理…..
高效的做法使用同样的条件(或者说是索引)只访问一次磁盘,低效的做法访问了2次磁盘,这样速度差别将近2倍。
游标里面不能嵌入查询(或者再嵌游标),其实也不能有update delete等语句,只能有insert语句。但在实际的编程情况下是不可能完全避免的,但我们一定要尽量避免。该类问题也是我们程序中出现过的问题,该类问题也可以大大提升程序效率,请大家一定注意。
Cursor cur_ac04 is
& Select aac001,akc010
& Where aab001=
prm_aab001;
For rec_ac04 in cur_ac04 loop
Into str_aac008
aac001=rec_ac04.aac001;
str_aac008=’1’ then
n_jfje := rec_ac04.akc010*0.08;
str_aac008=’2’ then
&&&&&n_jfje
:= rec_ac04.akc010*0.1;
Cursor cur_ac04 is
ac01.aac001,ac04.akc010,ac01.aac008
ac04.aac001=ac01.aac001
and aab001=
prm_aab001;
For rec_ac04 in cur_ac04 loop
rec.aac008=’1’ then
n_jfje := rec_ac04.akc010*0.08;
rec.aac008=’2’ then
n_jfje := rec_ac04.akc010*0.1;
优化的方法是尽量把游标循环中的查询语句放到游标查询中一起查询出来,这样相当于只访问了1次磁盘读到内存;如果放到游标中的话,假如游标有100万数据量,那么程序需要100万次磁盘,可以想象浪费了多少IO的访问。
如果在程序编写上没有办法避免游标中有查询语句的话(一般情况是可以避免的),那么也要保证游标中的查询使用的索引(即查询速度非常快),例如:游标100万数据量,游标中的查询语句执行需要0.02秒,从这个速度上来说是很快的,但总体上看100万*0.02秒=2万秒=5小时33分钟,如果写一个不够优化的语句需要1秒,那么需要几天能执行完呢?
all替换union
Union会去掉重复的记录,会有排序的动作,会浪费时间。因此在没有重复记录的情况下或可以允许有重复记录的话,要尽量采用union all来关联。
DECODE函数来减少处理时间
使用DECODE函数可以避免重复扫描相同记录或重复连接相同的表.
select count(1) from ac01 where aab001=’100001’ and
aac008=’1’;
select count(1) from ac01 where aab001=’100001’ and
aac008=’2’;(低效)
Select count(1),aac008
&From ac01
Where aab001=’100001’
& and aac008 in
(’1’,’2’)
group by aac008;
select count(decode(aac008,’1’,’1’,null)) zz,
count(decode(aac008,’2’,’1’,null)) tx
where aab001=’100001’;
特别说明:
by和order by 都会影响性能,编程时尽量避免没有必要的分组和排序,或者通过其他的有效的编程办法去替换,比如上面的处理办法。
by需要查询后排序,速度慢影响性能,如果查询数据量大,并且分组复杂,这样的查询语句在性能上是有问题的。
尽量避免使用分组或者采用上面的一节的办法去代替。
by的也一定要进行优化。
ac04.aac001,ac01.aac002,ac01.aac003,sum(aac040),ac01.aab001
&from ac04,ac01
&where ac04.aac001=ac01.aac001 and
ac01.aab001=''
ac04.aac001,ac01.aac002,ac01.aac003,ac01.aab001;
ac04.aac001,ac01.aac002,ac01.aac003,gzze,ac01.aab001
&from (select aac001,sum(aac040) gzze from ac04
group by aac001) ac04,ac01
&where ac04.aac001=ac01.aac001
aab001='';
by需要查询后排序,速度慢影响性能,如果查询数据量大,排序的时间就很长。但我们也不能避免不使用,这样大家一定注意一点的是如果使用order by那么排序的列表必须符合索引,这样在速度上会得到很大的提升。
子句替换HAVING子句
避免使用HAVING子句, HAVING
只会在检索出所有记录之后才对结果集进行过滤. 这个处理需要排序,总计等操作. 如果能通过WHERE子句限制记录的数目,那就能减少这方面的开销.
SELECT aac008,count(1)
GROUP BY aac008
HAVING aac008 in (‘1’,’2’);
SELECT aac008,count(1)
&FROM ac01
Where aac008 in (‘1’,’2’)
GROUP BY aac008 ;
中的条件一般用于对一些集合函数的比较,如COUNT() 等等.
除此而外,一般的条件应该写在WHERE子句中
当在SQL语句中连接多个表时,
请使用表的别名并把别名前缀于每个Column上.这样一来,就可以减少解析的时间并减少那些由Column歧义引起的语法错误.
一般数据转换的程序经常会使用到该方法。
最高效的删除重复记录方法 (
因为使用了ROWID)
DELETE FROM ac01 a
WHERE a.rowid & (SELECT MIN(b.rowid)
FROM ac01 b
WHERE a.aac002=b.aac002
and a.aac003=b.aac003 );
数据转换的程序需要关注这一点。
Commit执行也是有时间的,不过时间特别短,但提交频率特别大,必然也会浪费时间。
commit可以释放资源,在大量数据更新时,必须及时提交。
a. 回滚段上用于恢复数据的信息.
b. 被程序语句获得的锁
c. redo log buffer 中的空间
d. ORACLE为管理上述3种资源中的内部花费
Cur_ac20有5000万数据
in cur_ac20 loop
&& Insert into ac20
&& n_count := n_count +
&& If n_count = = 100000
then& --10万一提交
n_count := 0;
如果1条一提交,需要提交5000万必然浪费时间;如果整体提交,资源不能释放,性能必须下降。
在实际编程时,应注意提交的次数和提交的数据量的平衡关系。
表关联的越多,查询速度就越慢,尽量减少多个表的关联,建议表关联不要超过3个(子查询也属于表关联)。
数据转换上会存在大数据量表的关联,关联多了会影响索引的效率,可以采用建立临时表的办法,有时更能提高速度。
数据转换时或者大业务数据插入时,有以下几种办法进行数据插入(不包括imp、impdp和sqlloader)
Insert into
…select 方式
将查询的结果一次插入到目标表中。
Insert into ac01_bak select * from
由于是一次查询一次插入,并且最后一次提交,他的速度要比下面描述的curosr的方式速度要快。但查询插入的数据量过大必然会占用更多的内存和undo表空间,只能在插入完成后提交,这样资源不能释放,会导致回滚表空间不足和快照过旧的问题,另外一旦失败需要全部回滚。因此建议小数据量(例如:300万以下)的导入采用该种方式。
Insert into …
select方式
该种方式同上种方式,不过由于有append的提示,这种语句不走回滚段直接插入数据文件,速度非常快。注意系统开发编程不能使用该种方式,数据转换可以灵活使用。
Cursor方式
定义游标,然后逐行进行插入,然后定量提交。
cur_ac20 is
&& Select * from
rec_ac20 in cur_ac20 loop
&& Insert into
&&&(rec_ac20.aac001,
&& If n_count :==100000
n_count :=0;
批绑定的方式
通过游标查询将数据逐行写到数组里(实际上就是内存),然后通过批绑定的语句forall … in… insert
into…values…;将内存的数据一次写入到数据文件中。相比cursor的方式减少了对io的访问次数,提高了速度,但注意内存别溢出了。
在实际的应用系统中索引问题导致性能问题可能能占到80%,在程序优化上索引问题是需要我们特别关注的。本节主要描述什么情况索引会不生效。
这个问题是在我们实际编程中出现过的,请大家一定注意。在索引列上使用函数或运算,查询条件都不会使用索引。
不使用索引
Select * from ka02 where aka060=’’ and
to_char(aae030,’yyyymm’)=’200801’;
Select * from ka02 where aka060=’’ and
aae030=to_date(’200801’,’yyyymm’);
不使用索引
Select * from ka02 where aka060=’’ and
Select * from ac04 where aac001=’’ and
aae031=sysdate -1;
如果一定要对使用函数的列启用索引,
ORACLE新的功能: 基于函数的索引(Function-Based Index)
CREATE INDEX IDX_KA02_AKA066 ON KA02 (UPPER(AKA066));
SELECT * FROM KA02 WHERE UPPER(AKA066) = ‘ASPL’;
不是极特殊情况,建议不要使用。
索引列的条件如果类型不匹配,则不能使用索引。
不使用索引
from ac01 where aac001=;
from ac01 where aac001=’’;
避免在索引列上使用NOT,
NOT不会使查询条件使用索引。对于!=这样的判断也是不能使用索引的,索引只能告诉你什么存在于表中, 而不能告诉你什么不存在于表中
低效: (这里,不使用索引)
Where not aab019=’10’;
高效: (这里,使用了索引)
Where aab019 in (’20’,’30’);
虽然效果不是特别明显,但建议采用这种方式
WHERE aab019 & ‘10’
WHERE aab019 &=’20’
两者的区别在于, 前者DBMS首先定位到aab019=10的记录并且向前扫描到第一个aab019大于10的记录,而后者DBMS将直接跳到第一个aab019等于10的记录
和IS NOT NULL
对于索引列使用is
null或is not null不会使用上索引. 因为空值不存在于索引列中,所以WHERE子句中对索引列进行空值比较将使ORACLE停用该索引.
低效: (索引失效)
select * from ab01 where aab019
高效: (索引有效)
select * from ab01 where aab019 in(‘10’,’20’,’30’);
在实际开发中,对于这类的问题很难避免,如果不是特别影响速度或者要求速度的,可以忽略。
)的like语句
%在常量前面索引就不会使用。
不使用索引
from ac01 where aac002 like ‘%210104’;
from ac01 where aac002 like ‘!0104%’;
from ac01 where aac002 like ‘210104%’;
如果索引是建立在多个列上,
只有在它的第一个列被where子句引用时,优化器才会选择使用该索引。
Ac02的复合索引:aac001、aae140、aae041
from ac02 where aae140=’31’ and
aae041=’200801’;&&
--不会使用索引
from ac02 where
aac001=’’;&&
--可以使用索引
如果不使用索引第一列基本上不会使用索引,使用索引要按照索引的顺序使用,另外使用复合索引的列越多,查询的速度就越快
当SQL语句的执行路径可以使用分布在多个表上的多个索引时, ORACLE会同时使用多个索引并在运行时对它们的记录进行合并, 检索出仅对全部索引有效的记录.
在ORACLE选择执行路径时,唯一性索引的等级高于非唯一性索引. 然而这个规则只有
当WHERE子句中索引列和常量比较才有效.如果索引列和其他表的索引类相比较. 这种子句在优化器中的等级是非常低的.
如果不同表中两个相同等级的索引将被引用, FROM子句中表的顺序将决定哪个会被率先使用.
FROM子句中最后的表的索引将有最高的优先级.
如果同一表中有两个相同等级的索引被引用,oracle会分析最有效的索引去引用,其他的索引不会使用,如果这些相同等级的索引效果差不多,oracle可能会自动合并进行使用。
当ORACLE无法判断索引的等级高低差别,优化器将只使用一个索引,它就是在WHERE子句中被列在最前面的.
如果表中有两个以上(包括两个)索引,其中有一个唯一性索引,而其他是非唯一性.
在这种情况下,ORACLE将使用唯一性索引而完全忽略非唯一性索引.
对于表的访问,可以使用两种Hints. FULL 和 ROWID
FULL hint 告诉ORACLE使用全表扫描的方式访问指定表.
WHERE AAC001 = ‘’; 如果一个大表没有被设定为缓存(CACHED)表而你希望它的数据在查询结束是仍然停留 在SGA中,你就可以使用CACHE
hint 来告诉优化器把数据保留在SGA中.
hint 和 FULL hint 一起使用.
FROM AC01;
hint 告诉ORACLE使用TABLE ACCESS BY
ROWID的操作访问表. 采用TABLE ACCESS BY
ROWID的方式特别是当访问大表的时候, 使用这种方式,
你需要知道ROIWD的值或者使用索引.
告诉ORACLE使用基于索引的扫描方式.
你不必说明具体的索引名称
SELECT aac001
WHERE& aac002='1111111';
在不使用hint的情况下,
以上的查询应该也会使用索引,然而,如果该索引的重复值过多而你的优化器是CBO, 优化器就可能忽略索引.
在这种情况下,
你可以用INDEX
hint强制ORACLE使用该索引.
ORACLE hints 还包括ALL_ROWS,
FIRST_ROWS, RULE,USE_NL, USE_MERGE, USE_HASH 等等.
使用hint , 表示我们对ORACLE优化器缺省的执行路径不满意,需要手工修改. 这是一个很有技巧性的工作.
除非特定的情况,例如:数据转换,其他情况最好不用.
我们现在很多项目都存在性能问题,其中有很多种情况都是由于分析过旧导致ORACLE判断索引级别和资源成本上出现问题,会导致ORACLE判断错误不使用索引。我个人觉得这是ORACLE不够完善的地方。
解决办法:
第一种办法:删除分析,停止oracle10g的自动分析,但不使用分析,oracle访问数据的CPU消耗就过大。
第二种办法:重新分析,但过长时间后,索引是否会再次失效,没有验证过。
表上存在并行,ORACLE判断索引级别和资源成本上出现问题,会导致ORACLE判断错误不使用索引。
这个问题我不知道有什么好的处理办法,从现场实际应用速度角度比较,我还是选择去掉并行,因为不使用索引进行全表扫描肯定是不能忍受的。
索引的使用是肯定会大大提高查询的速度,但索引其实也是一种数据,它也是存放的用户类型的表空间下的,索引建立的越多越大,占用的空间也越大,从用户的环境来说这也不是问题,但如果一个表有过多过大的查询,必然会影响insert、delete和update索引列的速度,因为这些操作改变了整个表的索引顺序,oracle需要进行调整,这样性能就下降了。因此我们一定要合理的建立好有效的索引,编程也要符合索引的规则,而不能是索引符合编程的规则。
某项目数据转换,采用游标循环insert的方式,总共2000万的数据,总共用了4个小时,原因就是目标表里面有很多索引。解决方法是先删除索引再执行转换脚本,结果不用1小时就完成了,建立全部的索引不到半个小时。
原因就是第一种方式每次insert都改变索引顺序,共执行改变2000万次,而第二种方式整体上执行索引顺序就一次。
程序性能问题分析方法
本章主要介绍怎样找到出现性能问题PLSQL程序或语句的方法。
出现性能问题,我先要从整体进行分析,一般总体上会有几种现象:
整个系统运行速度都慢
在业务不忙的时候,所有模块都慢
只有在业务繁忙的时候,所有模块都慢
个别业务模块运行速度慢
在业务不忙的时候,该模块就慢
只有在业务繁忙的时候,该模块才慢
一般导致系统性能慢的因素:
硬件:客户端、服务器CPU、内存和存储设备配置不符合应用系统要求
网络:网速低、丢包
操作系统参数设置:参数设置不合理
受到其他软件干扰:例如:防火墙、病毒
Weblogic设置:参数设置不合理
Oracle设置:内存、表空间、redolog、系统参数设置不合理等
PLSQL程序:plsql不优化、未使用索引、锁表
在不同现象下,可能导致性能问题的因素:
一般来说,如果在不办理业务的情况下,整个系统性能就慢的话,应该和PLSQL程序优化是没有关系的。可能的因素为硬件、网络、操作系统、其他软件干扰、ORACLE设置。
只有在业务繁忙的时候,整体系统性能都慢,有可能的因素有硬件、操作系统设置、WEBLOGIC设置、ORACLE设置、PLSQL程序。如果在sqlplus下做查询都慢,那么就和weblogic没有关系。
一般来说,如果在不办理业务的情况下,个别业务模块速度就慢的话,那么基本上就是PLSQL程序不优化或未使用索引造成的。
只有在业务繁忙的时候,个别模块慢,有可能的因素有硬件、操作系统设置、WEBLOGIC设置、ORACLE设置、PLSQL程序、锁表。
这里我们重点是说明PLSQL优化、索引优化的问题,其他例如:硬件、网络、操作系统和oracle设置等因素我们不进行说明。
PLSQL优化、索引不使用的问题产生的影响:
对于某段不优化的程序或语句频繁或者全表扫描一个表时,它访问磁盘的时间和占用的吞吐量是很高的,这就导致系统IO长时间处于忙的状态,导致整个系统性能下降。
对于某段不优化的程序或语句频繁或者全表扫描一个表时,其他的业务程序也访问同一个表时,速度将大大下降。
如果是更新表操作时间长,还可能会导致锁等待,导致会话堵塞,weblogic端也出现压力问题,导致这个系统性能下降。
我们一般根据这些现象、以及一些方法判断,来初步分析产生性能问题的大致原因的范围。不过对于这一点,还是比较困难的,因为产生问题的原因是多种的,并且还有一定的关联。下面的章节介绍我们已经断定是PLSQL优化、索引不使用的问题,我们通过什么方法来具体定位问题。
Plan分析索引使用
Developer等工具有一个Expain Plan分析的功能,这个功能可以帮助我们分析SQL语句是否使用了索引、使用哪些索引和使用索引的效果。
选择explain plan的窗口
在上面栏中输入SQL语句,然后点击工具栏上的EXECUTE执行(或按F8),就会在下面显示Optmizergoal优化器的默认方式(也可手工选择),以及下面的解释计划,从解释计划上能看到哪个条件语句使用了索引,哪个没有使用;哪个表使用了索引,使用了哪个索引,哪些表是全表扫描的(TABLE ACCESS FULL)
分析内容说明:
COST:根据优化程序的基于开销的方法所估计出的操作开销值对于使用基于规则方法的语句该列为空该列值没有特定的测量单位它只是一个用于比较执行规划开销大小的权重值
Cardinality:根据基于开销的方法对操作所访问行数的估计值
Bytes:根据基于开销的方法对操作所访问字节的估计
通过设置,我们还能看到更多的信息,例如:CPU使用、时间等等
全表扫描的(TABLE ACCESS
FULL)肯定是速度慢的,如果是大数据量的表,那么这个语句是绝对影响性能的。
另外使用了索引也不一定性能就高,因为索引使用也有效率的情况,下面列出索引常见的使用类型:
INDEX UNIQUE
SCAN:唯一索引扫描,速度最快
RANGE SCAN:范围索引扫描,使用这个索引时,就需要看COST、Cardinality、Bytes的大小了,如果特别大,有时候还可能速度低于全表扫描的速度。
我们在知道语句有问题,或者我们对语句进行优化时,这个工具是非常有用的。
程序有性能问题的时候,我们是不知道哪些语句存在性能的问题,尤其你不是开发人员。幸好有一些工具可以帮助我们找到这些存在性能问题的语句。
Toad工具和ORACLE9I的企业管理控制台工具可以捕获到这些问题语句(oracle10g中em的功能不够好)。在TOAD和ORACLE9I工具中可以查询到TOPSQL顶级SQL的内容,通过CPU、IO吞吐量、占用时间等信息的排序,我们可以找到最影响系统性能的语句,通过分析我们可以看到这些语句的解释计划。
根据解释计划,我们可以进行语句的优化,我们知道语句后,我们通过plsql的搜索功能就知道存在问题语句的程序了。
这个办法使用有个前提条件就是这些问题语句在系统上运行过,并且没有间隔过长的时间,因此最好是在实际出现性能问题的ORACLE上不断的去监控,才能捕获到最全的问题语句。
ORACLE9i企业管理控制台工具的topsql
系统运行中的所有TOPSQL
分析具体的SQL语句
Sql分析的解释计划
TOPSQL分析也只能是找到未使用索引的语句(实际上这一点基本就足够解决性能的问题了),但是对于2.4章节中的很多内容,没有办法进行捕获。
我们可以采用针对性语句搜索,来尽量找到一些问题语句进行优化。在PLSQL工具中有一个Find DB
Object的功能,可以进行搜索。
我们可以搜索的关键特征信息:
tab、delete tab,其中tab是数据量特别大的表,我们可以针对性的检查对大表访问的语句(例如:ac20、ab09、kc22、kc24等)。
这种办法很有局限性,不过也是一种检查代码的办法。
以上的各种办法,基本都不能检查出类似2.4.8和2.4.9等问题,当我们不能通过整体上去发现问题的时候,我们对有性能问题程序直接进行后台的跟踪,有时候往往是最有效的。
用户的生产运行环境,数据库一般都是UNIX系统的小机。我们会在操作系统级上进行监控和ORACLE的session上进行监控。
UNIX下监控性能的命令:
topas可以观察CPU、内存、IO的使用,不过该命令不是所有的UNIX都通用
vmstat可以观察CPU和内存的使用情况。例如:vmstat
iostat可以观察IO的使用情况。例如:iostat
ps aux | head
-25查看cpu占用最高的进程
查询内存使用最高的进行命令:top
查看oracle进程命令:ps &ef|grep
通过ps找到进程的pid,我们也可以执行下面的语句查看进程具体运行的SQL语句的文本:
SELECT sql_text FROM v$sqltext a
& &WHERE (a.hash_value,
a.address) IN (
&& &SELECT
DECODE (sql_hash_value,0, prev_hash_value,sql_hash_value),
&& & DECODE
(sql_hash_value,0, prev_sql_addr, sql_address)
v$session b
&& & WHERE
b.paddr = (SELECT addr
v$process c
&& & WHERE
c.spid = '&pid'))
ORDER BY piece ASC
4.1 开发工具的目的
现在所有解决程序上的性能问题的办法,大部分都是在系统运行后的解决办法,我们想制作一个工具,该工具在开发阶段和测试阶段就可以直接找到存在问题的程序语句。这样可以大大提高程序上的风险,也可以提高代码检查和性能测试的工作量。
4.2 总体设计思想
对后台存储过程的程序文件进行遍历扫描,对SQL语句进行检查。
实现的功能:
检查程序中的SQL语句是否使用索引
查询具有特征的关键字的SQL语句。例如:NOT
检查游标中嵌入游标或查询的语句
检查列上使用了函数、运算的语句
检查超过3个表以上的关联语句
检查同一个表多次访问(不容易实现)
4.2.1 读取文件
逐行进行读取
4.2.2 捕获SQL语句
遇到SQL关键字开始记录,直到遇到“;”为止
建立分析表做保存
记录包体名、过程名、简略SQL、详细SQL、是否循环中
SQL去掉回车换行
截取前100个字符
4.2.3 SQL语句分析
4.2.4 设置关键字
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

我要回帖

更多关于 java程序性能优化 pdf 的文章

 

随机推荐