精华内容
下载资源
问答
  • PCI总线的特点
    千次阅读
    2019-08-24 18:39:49

    Q:PCI总线的特点?

    A:PCI总线是一种同步的独立于处理器的32位或64位局部总线,最高工作频率为33MHz,峰值速度在32位时为132MB/s,64位时为264MB/s。

    1. 高速性:PCI局部总线以33MHz的时钟频率操作,采用32位数据总线,数据传输速率可高达132MB/s,远超过以往各种总线。另外,PCI总线的主设备(Master)可与微机内存直接交换数据,而不必经过微机CPU中转,也提高了数据传送的效率;
    2. 即插即用性:PCI板卡的硬件资源则是由微机根据其各自的要求统一分配,绝不会有任何的冲突问题;
    3. 可靠性:PCI独立于处理器的结构,形成一种独特的中间缓冲器设计方式,将中央处理器子系统与外围设备分开。这样用户可以随意增添外围设备,以扩充电脑系统而不必担心在不同的时钟频率下会导致性能的下降。
    4. 复杂性:PCI总线强大的功能大大增加了硬件设计和软件设计的实现难度。
    5. 自动配置:PCI总线规范规定PCI板卡可以自动配置。PCI定义了3种地址空间:存储器空间、输入输出空间和配置空间,配个PCI设备中都有256字节的配置空间用来存放自动配置信息,当PCI板卡插入系统,BIOS将根据读到的有关该卡的信息,结合系统的实际情况为插卡分配存储地址、中断和某些定时信息。
    6. 共享中断:PCI总线是采用低电平有效方式,多个中断可以共享一条中断线。
    7. 扩展性好:如果需要把许多设备连接到PCI总线上,而总线驱动能力不足时,可以采用多级PCI总线,这些总线上均可以并发工作,每个总线上均可以挂接若干设计。因此PCI总线结构的扩展性非常好。
    8. 多路复用:在PCI总线中为了优化设计采用地址线和数据线共用一组物理线路,即多路复用。
    9. 严格规范:PCI总线对协议、时序、电气性能、机械性能等指标都有严格的规定,保证了PCI的可靠性和兼容性。
    更多相关内容
  • 编译器前端对中间代码进行优化 编译器后端对目标代码进行优化 两个编译器必须等价,编译的结果必须是正确的,即使有99.99%的可能性是不正确的,但是效率很好也不行,正确性是根本。 二、中间代码优化的分类 从...

    一、代码优化的阶段

    欲提高源程序的运行速度,需要经过几个阶段的优化:

    1. 用户对源程序进行优化(和编译器无关,与coder设计的算法有关)
    2. 编译器前端对中间代码进行优化
    3. 编译器后端对目标代码进行优化

    两个编译器必须等价,编译的结果必须是正确的,即使有99.99%的可能性是不正确的,但是效率很好也不行,正确性是根本。

    二、中间代码优化的分类

    从优化的种类来看,中间代码的优化可有如下分类:

    1. 局部优化

    循环上的优化(所有优化方法效果最好的)
    1. 循环不变体外提
    循环中不因循环而改变的部分可以提到循环的外部
    2. 削减运算强度
    在一些循环上的计算转换成另一种计算方式实现,比如b=a*2 -> b=a+a
    基本块的优化(按照某些规则划分成基本块)
    1. 常表达式节省
    2. 公共子表达式节省

    1. 全局优化

    全局数据流分析,从而使优化的效果更好
    考虑基本块里如何优化,已经得到的值和变量的表,全局得到更多的信息进行分析。
    在局部优化的基础上进行全局优化才有更大的提高,否则直接进行全局优化的提升效果不明显。

    三、常见的编译优化的种类

    1. 数学上的优化

    情况一:(主要是在生成中间代码的时候会产生)

    (-,a,0,t1) (*,a,1,t2)
    //这种a+0,和a*1的没有太大意义的运算,这样的四元式可以删除
    //正常写普通的代码一般不会出现这种情况
    //但是在一些不明显的地方,比如计算数组中的元素a[i]时,用【i-(数组下界)】xsize
    //数组下界为0的时候和size=1的时候都会产生上面的四元式
    //可直接换但是还要将运算结果进行处理
    

    情况二:

    2*a->a+a
    a^2->a*a
    

    原则上说,可以不计算的直接删去其四元式,直接写出结果;高运算强度的可以转化成低运算强度的。

    2. 表达式短路问题

    在这里插入图片描述
    如果在计算一个表达式的时候可以不用将整个表达式的值都计算出来就可以确定表达式的结果,在这种情况下,后面的计算可以省略。
    或运算:如果计算出第一个表达式的结果是1可以直接返回 true
    与运算:如果计算出第一个表达式的结果是0可以直接返回false

    3. 常表达式的节省

    • 计算过程中有一个表达式是33.14,这个实际上是两个常数,他的结果我是可以计算出来的,这样我们在编译的过程中把33.14算出来,在目标程序的进行中就不用进行计算了。
    • 通过编译程序将可以计算出的结果直接计算出来然后将相应位置替换成计算出的结果。
    • 把有关工作交给编译程序进行可以提高生成的目标程序的运行效率,编译程序可以稍微慢些的工作,因为最后看的还是生成的目标程序的运行效率。

    4. 公共子表达式节省(消除重复操作)

    在这里插入图片描述

    • 所谓公共子表达式即两个子表达式的计算结果是一样的,不需要重复的进行计算,第一次计算出来之后,后面的计算可以利用前面的计算结果。例如前面有表达式ab,后面又有表达式也是ab,而且在第二个表达式和第一个表达式中间,a和b的值没有被改变过,那第二个a*b表达式实际上是可以不用计算的,只需要把前面的计算结果拿过来就可以达到计算的目的。
    • 这种情况在下标变量的计算中体现的非常明显,比方说a[i][j]和a[i][k],下标变量的计算先计算a[i]的地址然后计算j,然后计算a[i][j]的地址,a[i][k]也是一样先计算a[i]的地址在根据k计算a[i][k]的地址,所以前面关于a[i]的计算结果是完全一样的。这样就可以不用重复计算,利用前面的结果达到计算目的。

    5. 循环不变量式外提

    在这里插入图片描述
    循环不变式外提,在循环中,如果有一个表达式的值在循环中不会改变,就需要把它提到循环体的外面去。比方说有一个双重循环1-100和1-100,那么整个两重循环计算下来就是1万次,比方说里面有一个ab的表达式,在循环过程中ab的值如果不改变,那他就重复计算了9999次,假如把ab提到循环体的外面只需要计算1次,在循环里只需要用到它的计算结果。所以这样的表达式在循环体里面是不变的,我们要把他提到循环体的外面,从而提高我们的执行效率,这种效率的提高是最高的。特别是计算量很大的情况下,比方说有多重循环,这种循环不不变式外提可以大大提高程序的执行效率,这种提高的效率大概可以提高十几倍甚至是几十倍,串式程序的并行处理很大的一个研究重点,都是放在循环的并行计算上,比方说1~1000次的循环把它分成段,在不同的处理机上进行执行,从而提高程序的执行效率

    6. 削减程序的运算强度

    在这里插入图片描述
    削减程序的运算强度。这个也通常是针对循环的,一种特例的情形,比方说在程序设计语言中通常来说,一般的程序循环有三种方式分别是:
    1)for循环(有的语言中也称作是步长式的循环),循环形式是for i=e1 to e2 ;step e3{} 也就是说它的执行是i开始获取一个循环初值e1,然后每次循环i都加上e3的值,一直当i大于e2就结束循环,比方说for1=1to 100;step 1,就是1-100步长是1执行100次。
    2)while循环,“当型循环”()
    3)直到型循环 do until ~~的形式

    7. 寄存器优化

    在这里插入图片描述

    生成目标代码的时候一定是和目标机相关的,对于目标机来说提供多少个寄存器,比方说提供了8个,当目标程序真正执行的时候,这8个寄存器是如何被分配的,这是一个问题。简单的说假如说寄存器有空闲的时候,分配方案比较简单,空闲的就分配,这个没问题,什么时候会有问题呢?
    有这样几种情况:
    要用寄存器的时候,是否有空闲的寄存器,如果没有空闲的怎么办?需要剥夺一个寄存器,如何来剥夺?类似的还有内存和外存进行淘汰页的算法是类似的,只不过这个是在更高一级的层面上,寄存器和内存间的变换。这是寄存器分配优化

    8. 消除无用语句,消除冗余代码

    在这里插入图片描述

    消除无用语句,消除冗余代码,假如一个条件语句,if e s1 else s2 ,如果表达式E的值是一个true,那么s2是不可能用到了,所以这个命令就可以删掉了,这个命令也直接可以用s1来替换掉,当然这是一种特殊的情形,产生冗余代码实际上也是这么产生的

    9. 中间变量优化

    在这里插入图片描述

    中间变量的优化,生成中间代码的时候会产生大量的临时变量,大量的临时变量的特点一般都是产生之后使用一次就会不再用了,如果是说有一些临时变量和另外一些临时变量之间没有交集的话,不需要为每一个临时变量都分配独立的存储单元。最简单的方式,把产生临时变量一直到使用临时变量这个区域比方说把它定义为临时变量的活动区,假如两个临时变量的活动区不相交,实际上他们可以共用同一个存储单元,那么这种优化实际上就是临时变量的存储空间上的优化

    10. 目标代码优化

    在这里插入图片描述

    是目标代码的优化,可以通过确定目标代码来减少目标程序的指令个数来提高目标程序的执行效率,比方说有一个变量的值在寄存器里,运算出来的中间结果在寄存器里,假如直接让他参与运算之后,就不用往内存中存了,什么时候需要存,什么时候不存,什么时候需要把它放在寄存器里,这就是需要对目标程序进行的一种优化,根据使用情况来进行。

    11. 全局优化

    在这里插入图片描述
    总而言之这种优化还有很多,比方说全局的数据流分析和全局的优化,因为前面考虑实现的时候由于优化的技术可能比较复杂,都是在局部区做的,比方说一个基本块上做的,要想做到全局的需要对全局的程序做全局的数据流分析,这样的话可能就更复杂了,如果没有特殊需求,一般来说是不做这样的优化的:
    第一个原因就是编译代价太大,因为要做各种各样的分析,导致编译代价很大。
    第二就是提高的效率也并不是十分的明显。

    如果说没有特殊的需求,前面做的局部优化已经能达到想要的效果,全局优化就不用做了,特殊需求的时候才想办法处理。

    ⚠️优化中要注意的一个问题就是优化是在保证正确的情况下进行的,任何一个程序的优化也不能做到最优,而是在一定程度上来提高程序的执行效率。所以优化的过程一定是在保证程序正确的前提下来进行的。

    四、基本块

    (一)基本块的定义

    在这里插入图片描述

    • 基本快:是一个命令的序列,每一条命令都是按照顺序来执行的,进入基本块只能从第一条命令进入,退出基本块只能从最后一条命令退出,也就是说基本块是一个整体,要执行的话就全都执行从头到尾的顺序执行,这样一个特性对于程序进行分析或者是对中间代码进行分析有什么好处呢?对程序基本块中变量的性质是可判定的,假如不是基本块的话,x=10;L y=x+1;如果说只能从x=10这条语句顺序执行的话,y=x+1,这个x就是一个已知的,就是10,y就是11.但是假如说它有另外一个入口,其他地方有一个goto L,就不能判断x的值是不是10,因为外面有一个转移,比方说x=1; goto L x的值就不一定是10了,不是基本块的话程序的性质就不太好判断
    • 假如说是一个基本块都是顺序往下执行的话,那么每一个变量的值是怎么获取的、怎么传播出来的,就可以判断出来,这对我们的处理就非常有意义。因此在基本块上做优化使得问题变的相对简单了。

    (二)基本块的划分原则

    在这里插入图片描述

    1. 进入一个程序,(整个程序的第一条)四元式就是一个基本块的入口四元式;
    2. 遇到一个转移性的四元式,这条转移性的四元式是结束了一个基本块,它的后续四元式就可以作为下一个基本块的第一条四元式;
    3. 遇到一个定位性的四元式或者是标号性的四元式,就结束一个基本块,并作为下一个基本块的第一条四元式;
    4. 那么遇到一些函数的结束标示,就结束当前的四元式。例如p=&x; *p=5; y=x+x; 因为p是间接取址的,所以要结束这个标准块,否则也还是不知道如何来判断。

    在这里插入图片描述
    比方说goto还有(then t1,- ,-)目标程序运行到这的时候要判断t1是真是假,如果是假的话就要跳过t1,所以一定是要产生一个跳转指令的,还比如else这种,也就是说s1执行完一定要产生一个跳转指令跳过s2。
    在这里插入图片描述
    比方说循环指令中的while四元式,当循环体循环结束之后要产生一个跳转指令,要转移到前面重复计算的表达式的位置,假如没有这样一个四元式, 就没有办法确定转移到什么地方。这样的四元式就起到一个定位型四元式,还有比方说endif等等。还有对间接变量的赋值,也表示一个基本块的结束,这是基本块划分的原则,总的来说最关键的两点就是遇到转移型四元式和定位型四元式的开始
    在这里插入图片描述
    在这里插入图片描述

    五、常表达式节省

    在编译过程中能够计算出值的表达式,就在中间代码这级给它计算一个结果,这样就不需要在目标程序执行的时候进行计算了。
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述

    1. 首先构造一个表,即变量的值表,表中元素是一个二元组,表项左部是一个变量名或者是一个临时变量,右边是已知它的值是什么,就填到这里。
    2. 以后的优化算法也就比较简单,通常来说是这样做的:进入到一个基本快的时候把这个表清空,遇到一个运算型的四元式,比方说有算符 a b t1,首先看一下a和b是不是常量,如果是常量当然可以进行计算,就把t1填到表里。如果是变量的话,就要去表中查一下有没有变量对应的值,如果有值,就把这个变量用值来替换然后来看看可不可以进行计算,能计算就进行计算,不能计算替换完了之后,值就放到四元式中。
    3. 如果遇到一个赋值型四元式,比方说b=a,就要到表里去查a有没有值,如果a是已知的,就把b填到表里,把a的值取出来填给b。按照这样顺序进行计算,能够算出常量值的四元式就被节省掉了。这里要注意,运算型的四元式实际上第一步,严格来说,用常量值替代运算符,比方说3*3.14 t1,就算出t1的结果,以后用到t1的时候就从表里取t1的值就可以了
    4. 中间可以夹杂着用常量定值表对原有四元式进行替换,如果四元式都变成常量的就删除,否则就留着

    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • 【编译原理】中间代码(一)

    万次阅读 多人点赞 2017-12-05 15:08:56
    在编译器的分析-综合模型中,前端对源程序进行分析并产生中间表示,后端在此基础上生成目标代码。理想情况下,和源语言相关的细节在前端分析中处理,而关于目标机器的细节则在后端处理。和中间代码相关的内容包括...

    在编译器的分析-综合模型中,前端对源程序进行分析并产生中间表示,后端在此基础上生成目标代码。理想情况下,和源语言相关的细节在前端分析中处理,而关于目标机器的细节则在后端处理。和中间代码相关的内容包括中间代码表示、静态类型检查和中间代码生成,本文将讨论关于中间代码表示的内容。

    有向无环图

    表达式的有向无环图(Directed Acyclic Graph,简称DAG)与语法分析树类似,一个DAG的叶子结点对应于原子运算分量,内部结点对应于运算符。与语法分析树不同的是,如果DAG中一个结点N表示一个公共子表达式,那么N可能有多个父结点。举个例子,表达式a+a*(b-c)+(b-c)*d的DAG如下:

    20171204_img1

    DAG的每个结点通常作为一条记录被存放在数组中,一个记录包括的结点信息有:

    • 结点标号:如果记录表示叶子结点,那么结点标号是该结点的文法符号;如果记录表示内部结点,那么结点标号是运算符;
    • 词法值:如果记录表示叶子结点,那么记录还包括该结点的词法值,通常是一个指向符号表的指针或者一个常量;
    • 左右子结点:如果记录表示内部结点,那么记录还包括该结点的左右子结点。

    由于一个DAG的结点都会保存在一个记录数组中,因此我们可以通过数组下标引用某个记录从而获取结点信息,这个数组下标称为相应结点的值编码

    对图1的DAG,它的记录数组为:

    20171204_img2

    其中,左边的下标是每个结点的值编码,并且在某些记录中可以包括值编码。例如:对于第5条记录,它表示内部结点”-“,该结点左边的子结点是叶子结点”b”,右边的子结点是叶子结点”c”,由于代表b和c的记录已经存在并且它们的值编码分别为2和3,因此内部结点”-“的记录为(-, 2, 3)。

    三地址代码

    三地址代码是形如x = y op z的指令集合,之所以名为“三地址代码”,是因为指令x = y op z具有三个地址:两个运算分量y和z,一个结果变量x。由于三地址代码会对多运算符算术表达式和控制流语句的嵌套结构进行拆分,因此适用于目标代码的生成和优化。

    三地址代码基于两个基本的概念:地址和指令。简单地说,地址就是运算分量,指令就是运算符,一个地址的表现形式可以是变量名、常量或者编译器生成的临时变量。下面是几种常见的三地址指令形式:

    20171204_img3

    除此之外,另一种方式是用记录表示三地址代码中的每条指令,四元式、三元式和间接三元式是三种用记录表示三地址代码的方式。

    四元式

    一个四元式是一条表示三地址指令的记录,它有4个字段:

    • op:表示一个运算符;
    • arg1:表示第一个运算分量;
    • arg2:表示第二个运算分量;
    • result:表示结果变量。

    一个四元式中可能用到了所有4个字段,也可能只用到了其中几个字段,它的几个特例如下:

    • 形如x = minus y的单目运算符指令不使用arg2字段,”minus”表示单目减运算符;
    • 形如x = y的赋值指令不使用arg2字段,并且它的op字段是”=”;
    • 形如param x的参数传递指令不使用arg2和result字段;
    • 条件和非条件转移指令将目标标号放入result字段。

    下图是一个例子,左边给出了三地址代码,右边是对应的四元式表示:

    20171204_img4

    三元式

    通过图2我们发现,一段三地址代码对应的四元式被存放在一个记录数组中,这一点和DAG结点的记录数组很像;另外,四元式中的result字段主要被用于保存临时变量名,这个临时变量是由编译器生成的。如果我们仿照DAG的记录数组用值编码表示临时变量的地址,那么就可以省略四元式中的result字段,三元式就是由此而来的。

    一个三元式只有3个字段:op、arg1和arg2,它们的含义和在四元式中相同。为了取代四元式中的result字段,三元式用值编码表示结果变量的地址。图2中三地址代码的三元式表示如下:

    20171204_img5

    在图3(b)中,表格左边的数字是值编码,它表示三元式的结果变量的地址,并且这些值编码可以在三元式中被使用(使用的时候用括号括起来)。另外,对形如x=y的赋值指令,和四元式不同的是,三元式的op字段是”=”,arg1字段是”x”,arg2字段是”y”。

    间接三元式

    三地址代码的三元式表示存在一个问题,如果记录数组中的某条记录R的位置发生改变,那么所有使用到记录R的值编码的记录都需要更新。举个例子,在图3(b)中,如果把第1和第2条记录的位置互换,那么第3和第4条记录的内容都会发生改变。为了解决这个问题,提出了用间接三元式来表示三地址代码。

    一个间接三元式在三元式的基础上增加了一个列表,这个列表包含了指向三元式的指针。仍以例子说明,下图是图3中三元式的间接三元式:

    20171204_img6

    图4(a)是图3(b)的间接三元式,它使用了一个instruction数组保存要执行的指令,每条指令是一个指向某个三元式的指针。这样的话,当我们改变指令顺序时,就不用再更新三元式了,如图4(b)所示。

    静态单赋值形式

    静态单赋值(Static Single Assignment,简称SSA)形式是另一种中间表示形式,它和三地址代码的主要区别在于:

    第一,SSA中的所有赋值都是针对具有不同名字的变量的,这也是“静态单赋值”名字的由来。这一特性如下图中表示:

    20171204_img7

    第二,由于同一个变量可能在两个不同的控制流路径中被定值,因此SSA使用一种被称为φ函数的表示规则将这个变量的两处定值合并起来。这一特性如下图所示:

    20171204_img8

    fightingZh
    欢迎关注微信公众号fightingZhヾ(◍°∇°◍)ノ゙

    展开全文
  • update查询

    千次阅读 2019-03-27 19:14:38
    1, 关联查询和非关联查询 在非关联查询中,内部查询只执行一次并返回它的值给外部查询,然后外部查询在它的处理中使用内部查询返回给它的值。而在关联查询中,对于外部查询返回的每一行数据,内部查询都要...

    基础知识
    1, 关联子查询和非关联子查询

    在非关联子查询中,内部查询只执行一次并返回它的值给外部查询,然后外部查询在它的处理中使用内部查询返回给它的值。而在关联子查询中,对于外部查询返回的每一行数据,内部查询都要执行一次。另外,在关联子查询中是信息流是双向的。外部查询的每行数据传递一个值给子查询,然后子查询为每一行数据执行一次并返回它的记录。然后,外部查询根据返回的记录做出决策。

    如:

    SELECT o1.CustomerID, o1.OrderID, o1.OrderDate
    FROM Orders o1
    WHERE o1.OrderDate = (SELECT Max(OrderDate)
    FROM Orders o2
    WHERE o2.CustomerID = o1.CustomerID)

    是一个关联子查询

    SELECT o1.CustomerID, o1.OrderID, o1.OrderDate
    FROM Orders o1
    WHERE o1.OrderDate IN
    (SELECT TOP 2 o2.OrderDate
    FROM Orders o2
    WHERE o2.CustomerID = o1.CustomerID)
    ORDER BY CustomerID

    是一个非关联子查询

    2, 提示(HINT)

    一般在优化时,无论采用基于规则的或是基于代价的方法,由Oracle系统的优化器来决定语句的执行路径。这样的选择的路径不要见得是最好的。所以,Oracle提供了一种方法叫提示的方法。它可以让编程人员按照自己的要求来选择执行路径,即提示优化器该按照什么样的执行规则来执行当前的语句。这样可以在性能上比起Oracle优化自主决定要好些。

    通常情况下,编程人员可以利用提示来进行优化决策。通过运用提示可以对下面内容进行指定:

    l SQL语句的优化方法;

    l 对于某条SQL语句,基于开销优化程序的目标;

    l SQL语句访问的访问路径;

    l 连接语句的连接次序;

    l 连接语句中的连接操作。

    如果希望优化器按照编程人员的要求执行,则要在语句中给出提示。提示的有效范围有限制,即有提示的语句块才能按照提示要求执行。下面语句可以指定提示:

    l 简单的SELECT ,UPDATE ,DELETE 语句;

    l 复合的主语句或子查询语句;

    l 组成查询(UNION)的一部分。

    提示的指定有原来的注释语句在加“+”构成。语法如下:

    [ SELECT | DELETE|UPDATE ] /*+ [hint | text ] */

    [ SELECT | DELETE|UPDATE ] --+ [hint | text ]

    注意在“/*”后不要空就直接加“+”,同样 “–+”也是连着写。

    警告:如果该提示语句书写不正确,则Oracle就忽略掉该语句。

    常见的提示有:

    Ordered 强制按照from子句中指定的表的顺序进行连接

    Use_NL 强制指定两个表间的连接方式为嵌套循环(Nested Loops)

    Use_Hash 强制指定两个表间的连接方式为哈希连接(Hash Join)

    Use_Merge 强制指定两个表间的连接方式为合并排序连接(Merge Join)

    Push_Subq 让非关联子查询提前执行

    Index 强制使用某个索引

    3, 执行计划

    在PL/SQL Developer的SQL WINDOWS中用鼠标或键盘选中SQL语句,然后按F5,就会出现执行计划解析的界面:

    4, Update的特点

    Update的系统内部执行情况可以参照附文:对update事务的内部分析.doc

    使用Update的基本要点就是,

    1) 尽量使用更新表上的索引,减少不必要的更新

    2) 更新的数据来源花费时间尽可能短,如果无法做到就把更新内容插入到中间表中,然后给中间表建上索引,再来更新

    3) 如果更新的是主键,建议删除再插入。

    5, 示例用表

    后面的阐述将围绕以下两张表展开:

    Create table tab1 (workdate varchar2(8), cino varchar2(15), val1 number, val2 number);
    Create table tab2 (workdate varchar2(8), cino varchar2(15), val1 number, val2 number);
    Create table tab3 (workdate varchar2(8), cino varchar2(15), val1 number, val2 number);
    Create table tab4 (workdate varchar2(8), cino varchar2(15), val1 number, val2 number);workdate, cino为两张表的关键字,默认情况没有建主键索引。

    二,Update两种情况

    用Update更新某个表,无外乎是两种情况:根据关联子查询,更新字段;通过非关联子查询,限定更新范围。如果还有第三种情况,那就是前两种情况的叠加。

    1, 根据关联子查询,更新字段

    Update tab1 t
    Set (val1, val2) = (select val1, val2
    from tab2
    where workdate = t.workdate
    and cino = t.cino);

    通过tab2来更新tab1的相应字段。执行SQL语句时,系统会从tab1中一行一行读记录,然后再通过关联子查询,找到相应的字段来更新。关联子查询能否通过tab1的条件快速的查找到对应记录,是优化能否实现的必要条件。所以一般都要求在tab2上建有Unique或者排重性较高的Normal索引。执行所用时间大概为(查询tab1中一条记录所用的时间 + 在tab2中查询一条记录所用的时间)* tab1中的记录条数。

    如果子查询条件比较复杂,如以下语句:

    Update tab1 t
    Set (val1, val2) = (select val1, val2
    from tab2 tt
    where exists (select 1
    from tab3
    where workdate = tt.workdate
    and cino = tt.cino)
    and workdate = t.workdate
    and cino = t.cino);这时更新tab1中的每条记录花费在子查询上的时间将成倍增加,如果tab1中的记录数较多,这种更新语句几乎是不可完成。

    解决方式是,把子查询提取出来,做到中间表中,然后给中间表建上索引,用中间表来代替子查询,这样速度就能大大提高:

    Insert into tab4
    select workdate, cino, val1, val2
    from tab2 tt
    where exists (select 1
    from tab3
    where workdate = tt.workdate
    and cino = tt.cino);
    create index tab4_ind01 on tab4(workdate, cino);

    Update tab1 t
    Set (val1, val2) = (select val1, val2
    from tab4 tt
    where workdate = t.workdate
    and cino = t.cino);

    2, 通过非关联子查询,限定更新范围

    Update tab1 t
    set val1 = 1
    where (workdate, cino) in (select workdate, cino from tab2)

    根据tab2提供的数据范围,来更新tab1中的相应记录的val1字段。

    在这种情况下,系统默认执行方式往往是先执行select workdate, cino from tab2子查询,在系统中形成系统视图,然后在tab1中选取一条记录,查询系统视图中是否存在相应的workdate, cino组合,如果存在,则更新tab1,如果不存在,则选取下一条记录。这种方式的查询时间大致等于:子查询查询时间 + (在tab1中选取一条记录的时间 + 在系统视图中全表扫描寻找一条记录时间)* tab1的记录条数。其中“在系统视图中全表扫描寻找一条记录时间”会根据tab2的大小而有所不同。若tab2记录数较小,系统可以直接把表读到系统区中;若tab2记录数多,系统无法形成系统视图,这时会每一次更新动作,就把子查询做一次,速度会非常的慢。

    针对这种情况的优化有两种

    1) 在tab1上的workdate, cino字段上加入索引,同时增加提示。

    修改以后的SQL语句如下:

    Update /+ordered use_nl(sys, t)/ tab1 t
    set val1 = 1
    where (workdate, cino) in (select workdate, cino from tab2)

    其中sys表示系统视图。如果不加入ordered提示,系统将会默认以tab1表作为驱动表,这时就要对tab1作全表扫描。加入提示后,使用系统视图,即select workdate, cino from tab2,作为驱动表,在正常情况下,速度能提高很多。

    2) 在tab2表上的workdate, cino字段加入索引,同时改写SQL语句:

    Update tab1 t
    set val1 = 1
    where exists (select 1
    from tab2
    where workdate = t.workdate
    and cino = t.cino)

    三,索引问题

    update索引的使用比较特殊,有时看起来能用全索引,但实际上却只用到一部分,所以建议把复合索引的各字段写在一起。

    例如:

    Update /+ordered use_nl(sys, t)/ tab1 t
    set val1 = 1
    where cino in (select cino from tab2)
    and workdate = ‘200506’

    这条SQL语句是不能完全用到tab1上的复合索引workdate + cino的。能用到的只是workdate=’200506’的约束。

    如果写成这样,就没问题:

    Update /+ordered use_nl(sys, t)/ tab1 t
    set val1 = 1
    where (workdate, cino) in (select workdate, cino from tab2)

    展开全文
  • 第七章 语义分析和中间代码生成

    万次阅读 多人点赞 2018-01-14 20:35:55
    1、 编译程序的任务是把源语言程序翻译成目标程序,有些编译程序在编译过程中,不产生中间语言,而是直接从源语言程序翻译成目标语言程序。  以上编译过程省略了中间语言,它不利于编译所产生的目标代码的...
  • 1.后缀式的特点是什么?2.如何将中缀式转换成后缀式?二、图表示法1.什么是抽象语法树,举例说明?2. 举例说明什么是DAG,与抽象语法树有什么区别?3.产生赋值语句抽象语法树的属性文法三、地址码1.什么是三地址码?...
  • Spark概述、Spark特点

    千次阅读 2017-07-05 16:38:41
    一、 Spark概述1....Spark是一种快速、通用、可扩展的大数据分析引擎,2009年诞生于加州大学伯克利分校AMPLab,2010年开源,...目前,Spark生态系统已经发展成为一个包含多个项目的集合,其中包含SparkSQL、Spark St
  • 服务器架构模式BS和CS的特点与区别

    千次阅读 2019-10-22 15:15:10
    服务器端:提供数据服务,操作数据,然后把结果返回中间层,结果显示在系统界面上。 中间件:这是运行在浏览器和服务器之间的。这层主要完成系统逻辑,实现具体的功能,接受用户的请求并把这些请求传送给服务器,...
  • 重温数据结构:理解 B 树、B+ 树特点及使用场景

    万次阅读 多人点赞 2018-05-29 00:46:13
    大家好,前面那篇文章《3 分钟理解完全二叉树、平衡二叉树、二叉查找树》中我们了解了几种特殊的二叉树的功能及特点,知道了它们在进行查找数据时可以提高效率,但需要注意的是,这是指在内存中进行查找。...
  • 电子科技大学 - 嵌入式系统及应用期末复习提纲

    千次阅读 多人点赞 2020-09-06 20:23:17
    中断管理 时间管理 任务扩展功能 嵌入式TCP/IP特点: 可裁剪 采用“零拷贝”技术,提高实时性 采用静态分配技术 2.9 嵌入式开发工具的哪两个特性影响嵌入式系统的开发效率? 集成度 可用性 2.10 嵌入式软件开发工具...
  • Qt编写可视化大屏电子看板系统1-布局方案

    万次阅读 多人点赞 2019-05-12 16:13:31
    三、功能特点 采用分层设计,整体总共分三级界面,一级界面是整体布局,二级界面是单个功能模块,三级界面是单个控件。 控件包括饼图、圆环图、曲线图、柱状图、柱状分组图、横向柱状图、横向柱状分组图、合格率...
  • 即时编译器的中间表达形式(IR)

    千次阅读 2019-12-20 11:35:17
    其中,前端会对所输入的程序进行词法分析、语法分析、语义分析,然后生成中间表达形式,也就是 IR(Intermediate Representation )。后端会对 IR 进行优化,然后生成目标代码。 如果不考虑解释执行的话,从 Ja...
  • Qt编写的项目作品6-可视化大屏电子看板系统

    千次阅读 多人点赞 2020-01-12 15:05:34
    一、功能特点 整体总共分三级界面,一级界面是整体布局,二级界面是单个功能模块,三级界面是单个控件。 控件包括饼图+圆环图+曲线图+柱状图+柱状分组图+横向柱状图+横向柱状分组图+合格率控件+百分比控件+进度...
  • 一文详解SQL关联查询

    千次阅读 2021-03-30 13:42:20
    简介:本文主要介绍什么是关联查询以及如何将关联查询改写为普通语义的sql查询。 本文主要介绍什么是关联查询以及如何将关联查询改写为普通语义的sql查询。 在背景介绍中我们将讲讲常见的关联查询的...
  • } 静态:长度固定 动态:不够存放可以加空间(搬家) /* 任务名任务:1_2 动态顺序存储线性表的基本实现 */ #include #include #include #define LIST_INIT_SIZE 100 #define LISTINCREMENT 10 #define Status int...
  • 总结:reads两端的错误率会高,中间低,如果中间高说明有问题。 4.测序数据质量分布 测序数据质量主要分布在Q30以上占比80%,这样的数据才能保证后续的分析 5.测序数据质量情况汇总 根据Illumina平台测序特点,...
  • 从上面的表中可以了解到的交易特点如下: 最好把限价单放在更活跃的那一方,比如说如果有很多的市场卖单出现在市场当中,那就最好多投放一些限价买单。 交易策略不具有方向性,也就是说并不是追逐市场价格而做决策是...
  • Qt编写数据可视化大屏界面电子看板系统

    万次阅读 多人点赞 2019-05-05 22:31:19
    ) 四、功能特点 采用分层设计,整体总共分三级界面,一级界面是整体布局,二级界面是单个功能模块,三级界面是单个控件。 控件包括饼图、圆环图、曲线图、柱状图、柱状分组图、横向柱状图、横向柱状分组图、合格...
  • css布局左右定宽,中间自适应

    千次阅读 2016-12-05 20:44:46
    一、基于传统的position或者浮动,让其脱离文档流的方法1、position(绝对定位法)绝对定位法原理是将左右两边使用absolute定位,因为绝对定位使其脱离文档流...留出左右元素的宽度,既可以使中间元素自适应屏幕宽度。
  • 查询的基本操作     1选择操作 对应的是限制条件(格式类似...是尽量减少连接操作前的元素组,使得中间临时关系尽量少(元组数少,连接得到的元组数就少) 好处: 这样可能减少IO和CPU的消耗、节约内存空间。...
  • 最大连续数组的三种解决方案

    千次阅读 2019-03-18 23:46:08
    开始思考,最大子数组的特点,最大子数组一定是从大于0的数字开始,并且以大于0的数字结束。否则这个连续数组可以去掉这个值,数组的和可以更大。于是,在这里引出了算法复杂度为O(n)的线性时间的排序算法。 ...
  • 超硬核!数据结构学霸笔记,考试面试吹牛就靠它

    万次阅读 多人点赞 2021-03-26 11:11:21
    但是没必要,我们可以通过分析计算来确定一个方法的好坏,用O()表示,括号内填入N、1,等式。 这到底是什么意思呢? 简单来说,就是这个方法,时间随着数据规模变化而增加的快慢。时间可以当成Y,数据规模是X,y=...
  • 流行的编程语言及其特点

    千次阅读 2019-04-17 20:08:00
    3. 分布式:Java包括一个支持HTTP和FTP等基于TCP/IP协议的库。因此,Java应用程序可凭借URL打开并访问网络上的对象,其访问方式与访问本地文件系统几乎完全相同。 4. 健壮:Java致力于检查程序在编译和运行时...
  • 中间业务系统

    千次阅读 2014-10-17 17:53:58
    三、中间业务系统 中间业务,在狭义上理解为:为中间的或代理的业务,即商业银行较多地以中间人的身份替客户办理收付和其他委托事项,提供各类金融服务并收取手续费的业务;在广义上理解为:不构成商业银行资产...
  • 三、功能特点 采用分层设计,整体总共分三级界面,一级界面是整体布局,二级界面是单个功能模块,三级界面是单个控件。 控件包括饼图、圆环图、曲线图、柱状图、柱状分组图、横向柱状图、横向柱状分组图、合格率...
  • 超硬核!操作系统学霸笔记,考试复习面试全靠它

    万次阅读 多人点赞 2021-03-22 18:43:49
    wait操作即在申请资源,signal操作是释放资源 wait操作其实就是进入临界区之前的进入区,signal操作是从临界区出来之后的退出区 原子操作的特点,操作一开始执行,半中间不可以打断,原语即为原子操作。 整型信号量...
  • 一文读懂区块链电子发票

    万次阅读 2018-08-18 10:27:35
    区块链实际上切断了中间人,取消所有中介,使得支付和交易的处理速度更快。因为整个过程都是完全数字化的,并且数据库是共享的,每个人都可以上链查询,不再需要手动扫描发票,也极大地加快了对账过程。  最重要...
  • 各种数据结构的简单特点 1、列表 包括 (1)数组 【1】会在内存中开辟一个连续的内存空间 【2】随机访问的效率比链表高。数组只要给定下标,则可以直接定位到该下标所对应的元素,而链表每次都是从头节点开始...
  • java容器类用法与特点总结

    千次阅读 2021-01-24 15:27:01
    此外,容器类提供的迭代器都有一个特点都会在迭代中间进行结构性变化检测,如果容器发生了结构性变化,就会抛出 ConcurrentModificationExcep,所以不能在迭代中间直接调用容器类提供的 add/remove方法,如需添加和...
  • hive查询sql效率优化

    千次阅读 2018-03-21 19:27:12
    今天写了个sql跑了好久,老大过来一看指点下,多用查询,多用where,然后在join, 提高十多倍,神奇了。想了想,还是老大经验丰富。 如果先join,就全表扫描,然后最后where最后筛选,比较耗时。 如果用查询...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 139,356
精华内容 55,742
关键字:

中间子特点