各位,大家好!
    本人现在接到一个需求,要高效的实现一个数据提取清单!
    具体情况是这样的,有表Table_A和Table_B。
    表Table_A和Table_B都有字段C_num,C_Date,C_chanel.其中C_num是主键。并表的数据的数量级都是20W以上。每天都有新的数据插入这两张表。
    现在要查询出当天之前Table_B没有而Table_A有的记录。
    我写的查询语句是
 select a.C_num, a.C_Date, a.C_chanel
  from Table_A a
 where a.C_Date < sysdate
   and not exists
 (select 'X' from Table_B t where t.C_num = a.C_num)
  但要花费890S以上的时间,请问下各位大虾,有没有更高效的查询方法?谢谢!
   

解决方案 »

  1.   

    用外关联能提高性能:select a.C_num, a.C_Date, a.C_chanel 
      from Table_A a LEFT OUTER JOIN Table_B b
        on (a.C_num = b.C_num)
     WHERE a.C_Date < sysdate 
       AND b.C_num IS NULL;
      

  2.   

    我觉得你的sql语句应该最好的了,建议你在A表的C_date上建议索引,再试一下
      

  3.   

    关于OUTER JOIN的说明见:http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/queries006.htm#insertedID6
      

  4.   

    比较赞同二楼的方法,加在索引
    一楼的写法似乎有点问题,
    and b.C_Num is null这一句会不会先过虑掉b表的再做left join?
    有没有高人帮忙解答一下
      

  5.   

    楼主的问题是一个典型的外连接问题,建议楼主先测试一下,下面给出了一个通用的例子,一试便知,另外建议楼主学习一下外连接,相信对你会有帮助的--建立表t_a
    create table t_a
    (c_num NUMBER,
    c_date DATE);--建立表t_b
    create table t_b
    (c_num NUMBER,
    c_date DATE);--向表t_a插入数据
    INSERT INTO t_a
    SELECT rownum, CREATED FROM user_objects WHERE rownum <= 10;--向表t_b插入数据
    INSERT INTO t_b
    SELECT rownum, CREATED FROM user_objects WHERE rownum <= 5;--两表外连接,查询a表所有的数据及b表对应的数据
    SELECT a.c_num, a.c_date, b.c_num, b.c_date
      FROM t_a a LEFT OUTER JOIN t_b b
       ON (a.c_num = b.c_num);--两表外连接,查询a表所有的数据而b表没有的数据
    SELECT a.c_num, a.c_date, b.c_num, b.c_date
      FROM t_a a LEFT OUTER JOIN t_b b
       ON (a.c_num = b.c_num)
      WHERE b.c_num IS NULL;
      

  6.   

    多谢楼上的热心帮助!
    我认为像这样的查询not in 的效率是最低的,其次是外连接。再就是not exists 。
    不过实践是检验真理的唯一标准,楼上帅哥的方法我会试一下的。
    再次感谢您的热心帮助!
      

  7.   

    多谢楼上的热心帮助!
    我认为像这样的查询not in 的效率是最低的,其次是外连接。再就是not exists 。
    不过实践是检验真理的唯一标准,楼上帅哥的方法我会试一下的。
    再次感谢您的热心帮助!
      

  8.   

    多谢楼上的热心帮助!
    我认为像这样的查询not in 的效率是最低的,其次是外连接。再就是not exists 。
    不过实践是检验真理的唯一标准,楼上帅哥的方法我会试一下的。
    再次感谢您的热心帮助!
      

  9.   

    你的认识首先就有错误,NOT EXISTS 可能会效率高于 NOT IN(并不是所有情况下),但是低于连接.
      

  10.   

    20W的数据量,1400秒,是很不应该了。
    两个表中的c_num 是主键,C_Date 上建立索引了吗?
      

  11.   

    Table_A是114W的数据量,Table_B是28W的数据量。又将这两个SQl跑一遍。NOT EXISTS用了大约720S,外连接的用了大约719S。都查不多。大概现在下班了。数据库现在没什么压力的吧。哪种效率高还很难说。
    但我需要的是将运行数据压缩在5分钟之内。不知道有没有办法。改加索引我没权限。再就是库中没有Table_B这个表。库中的Table_B是通过DBLink来查的。谢谢各位的帮助!
      

  12.   

    你把执行计划贴出来看看,如果是dblink那么速度肯定会慢一点的,因为必竟要去联接另一个数据库
      

  13.   

    试试这个:
    select /*+driving_site(a)*/ a.C_num, a.C_Date, a.C_chanel 
      from Table_A a 
     where not exists(select 1 from Table_B t where t.C_num = a.C_num) 
           and a.C_Date < sysdate 
      

  14.   

    select a.C_num, a.C_Date, a.C_chanel 
      from Table_B b, Table_A a
    where a.C_num = b.C_num(+) AND
          NVL(b.C_num, 0) = 0    AND
          a.C_Date < sysdate 
    然后在Table_B上建函数索引NVL(b.C_num, 0)
      

  15.   


    我觉得你说的和写的不是一个意思啊?
    你写的是当天之前Table_A有而Table_B没有的记录吧!
      

  16.   

    Table_B没有而Table_A有用那个集合操作的运送符啊!!
      

  17.   

    由于楼主的表每天都会有新数据增加,建议楼主把表结构改成分区表,再加上索引,用左连接LEFT JOIN 肯定比in快!
      

  18.   

    建義使用外關聯select *
     from table_A a,table_b b
    where a.c_num = b.c_num(+)
      and b.c_num is null
      and a.c_date < sysdate