select ly.ziliao_id,ly.create_date, cc
  from ly_release ly
  left outer join(
  select ziliao_id,count(ziliao_id) as cc
  from ly_cc
  where create_ly_cc_time >= trunc(sysdate) - 40
  group by ziliao_id
  ) ly_cc on ly.ziliao_id = ly_cc.ziliao_id 
                           
 where exists (select null
          from ly_release ly2, ly_ziliao zl
         where ly.create_date > =trunc(sysdate) - 40
           and zl.ziliao_id = ly.ziliao_id)这样执行了,平均21秒多,至少运行了10次
ly_cc 才2284条记录
ly_release 348221
ly_ziliao 7766
在时间上已经做索引了,不知道为什么还这么慢
这三个表的记录只会增加不会减少

解决方案 »

  1.   

    还没见过exists 后面用 select null的...楼下哪位高人来解答下...
      

  2.   

    WHERE EXISTS后面可以不要吧?语句的逻辑貌似有些混乱;
    关联查询优化的一条重要准则就是选择数据最少最合适的数据集或表来作为驱动表。你的语句貌似用ly_release做的驱动表,而ly_release却是表中数据最多的~~--try it
    select ly.ziliao_id,ly.create_date, cc
      from (
      select ziliao_id,count(ziliao_id) as cc
      from ly_cc
      where create_ly_cc_time >= trunc(sysdate) - 40
      group by ziliao_id
      ) ly_cc inner join   ly_release ly on ly_cc.ziliao_id =  ly.ziliao_id
      

  3.   

    还没见过exists 后面用 select null的... 
    后面用什么都行
      

  4.   

    WHERE EXISTS后面可以不要吧
    后面应该没用
      

  5.   

    联查询优化的一条重要准则就是选择数据最少最合适的数据集或表来作为驱动表
    什么叫驱动表
    是form后面的第一个表吗
    我在看了   http://topic.csdn.net/t/20021206/09/1236076.html
    还不明白 
      

  6.   

    你看的这个帖子有点老了,现在ORACLE用的大部分是CBO优化器(基于代价进行优化)而不是RBO优化器了(基于规则进行优化),
    虽然ORACLE二者都包含
      

  7.   

    我去掉了 WHERE EXISTS后面可以不要吧 
    1秒多就好了
    但还不明白什么叫驱动表 
    oracle 两者包含不是驱动表不是驱动表没关系了啊
      

  8.   

    嵌套循环(Nested Loops, NL)
            这个连接方法有驱动表(外部表)的概念。其实,该连接过程就是一个2层嵌套循环,所以外层循环的次数越少越好,这也就是我们为什么将小表或返回较小row source的表作为驱动表(用于外层循环)的理论依据。但是这个理论只是一般指导原则,因为遵循这个理论并不能总保证使语句产生的I/O次数最少。有时不遵守这个理论依据,反而会获得更好的效率。如果使用这种方法,决定使用哪个表作为驱动表很重要。有时如果驱动表选择不正确,将会导致语句的性能很差、很差。内部连接过程:
    Row source1的Row 1 --------------       -- Probe ->       Row source 2
    Row source1的Row 2 --------------       -- Probe ->       Row source 2
    Row source1的Row 3 --------------       -- Probe ->       Row source 2
    …….
    Row source1的Row n --------------       -- Probe ->       Row source 2
            从内部连接过程来看,需要用row source1中的每一行,去匹配row source2中的所有行,所以此时保持row source1尽可能的小与高效的访问row source2(一般通过索引实现)是影响这个连接效率的关键问题。这只是理论指导原则,目的是使整个连接操作产生最少的物理I/O次数,而且如果遵守这个原则,一般也会使总的物理I/O数最少。但是如果不遵从这个指导原则,反而能用更少的物理I/O实现连接操作,那尽管违反指导原则吧!因为最少的物理I /O次数才是我们应该遵从的真正的指导原则,在后面的具体案例分析中就给出这样的例子。        在上面的连接过程中,我们称Row source1为驱动表或外部表。Row Source2被称为被探查表或内部表。        在NESTED LOOPS连接中,Oracle读取row source1中的每一行,然后在row sourc2中检查是否有匹配的行,所有被匹配的行都被放到结果集中,然后处理row source1中的下一行。这个过程一直继续,直到row source1中的所有行都被处理。这是从连接操作中可以得到第一个匹配行的最快的方法之一,这种类型的连接可以用在需要快速响应的语句中,以响应速度为主要目标。        如果driving row source(外部表)比较小,并且在inner row source(内部表)上有唯一索引,或有高选择性非唯一索引时,使用这种方法可以得到较好的效率。NESTED LOOPS有其它连接方法没有的的一个优点是:可以先返回已经连接的行,而不必等待所有的连接操作处理完才返回数据,这可以实现快速的响应时间。        如果不使用并行操作,最好的驱动表是那些应用了where 限制条件后,可以返回较少行数据的的表,所以大表也可能称为驱动表,关键看限制条件。对于并行查询,我们经常选择大表作为驱动表,因为大表可以充分利用并行功能。当然,有时对查询使用并行操作并不一定会比查询不使用并行操作效率高,因为最后可能每个表只有很少的行符合限制条件,而且还要看你的硬件配置是否可以支持并行(如是否有多个CPU,多个硬盘控制器),所以要具体问题具体对待。
      

  9.   


    Driving Table(驱动表)
            该表又称为外层表(OUTER TABLE)。这个概念用于嵌套与HASH连接中。如果该row source返回较多的行数据,则对所有的后续操作有负面影响。注意此处虽然翻译为驱动表,但实际上翻译为驱动行源(driving row source)更为确切。一般说来,是应用查询的限制条件后,返回较少行源的表作为驱动表,所以如果一个大表在WHERE条件有有限制条件(如等值限制),则该大表作为驱动表也是合适的,所以并不是只有较小的表可以作为驱动表,正确说法应该为应用查询的限制条件后,返回较少行源的表作为驱动表。在执行计划中,应该为靠上的那个row source,后面会给出具体说明。在我们后面的描述中,一般将该表称为连接操作的row source 1。Probed Table(被探查表)
            该表又称为内层表(INNER TABLE)。在我们从驱动表中得到具体一行的数据后,在该表中寻找符合连接条件的行。所以该表应当为大表(实际上应该为返回较大row source的表)且相应的列上应该有索引。在我们后面的描述中,一般将该表称为连接操作的row source 2。
      

  10.   

    有些晦涩难懂了~~有些部分我也不是很明白。反正LZ要知道有这么一个概念就可以了。
    有时候,还需要用HINTS来指定哪个表为驱动表,用哪种优化器,下面是HINTS的一些作用:
     基于代价的优化器是很聪明的,在绝大多数情况下它会选择正确的优化器,减轻了DBA的负担。但有时它也聪明反被聪明误,选择了很差的执行计划,使某个语句的执行变得奇慢无比。此时就需要DBA进行人为的干预,告诉优化器使用我们指定的存取路径或连接类型生成执行计划,从而使语句高效的运行。例如,如果我们认为对于一个特定的语句,执行全表扫描要比执行索引扫描更有效,则我们就可以指示优化器使用全表扫描。在ORACLE中,是通过为语句添加 hints(提示)来实现干预优化器优化的目的。         hints是oracle提供的一种机制,用来告诉优化器按照我们的告诉它的方式生成执行计划。我们可以用hints来实现:
    1) 使用的优化器的类型
    2) 基于代价的优化器的优化目标,是all_rows还是first_rows。
    3) 表的访问路径,是全表扫描,还是索引扫描,还是直接利用rowid。
    4) 表之间的连接类型
    5) 表之间的连接顺序
    6) 语句的并行程度
      

  11.   

    指示连接顺序的hints:
    ORDERED  /*+ ORDERED */
            按from 字句中表的顺序从左到右的连接select /*+ORDERED*/  ly.ziliao_id,ly.create_date, cc
      from (
      select ziliao_id,count(ziliao_id) as cc
      from ly_cc
      where create_ly_cc_time >= trunc(sysdate) - 40
      group by ziliao_id
      ) ly_cc inner join   ly_release ly on ly_cc.ziliao_id =  ly.ziliao_id
      

  12.   

    ly_release 与 ly_ziliao 做了笛卡尔乘积,我想可能是你的SQL写错了。