这个sql查询语句效率太低了,数据量非常大查下要10秒左右,太慢了。怎样改效率高。非常感谢select * from D_JLX
where  ZDBM in(select JLX from DZ_ZZXX where substr(JWZRQ,0,8)='32100254')

解决方案 »

  1.   

    用EXISTS替代IN
    分页查询
    加索引
     select top 10 * from  
    (select top 10000010 * from tb order by id) a 
    order by id desc 
      

  2.   

    select * from D_JLX
    where  exists (select JLX from DZ_ZZXX where D_JLX.ZDBM = DZ_ZZXX.JLX AND substr(JWZRQ,0,8)='32100254')
      

  3.   

    1.用EXISTS替代IN
    2.分页查询
    3.加索引
      

  4.   


    select * 
      from D_JLX  d, DZ_ZZXX  x
     where  d.ZDBM = x.JLX
       and  substr(x.JWZRQ,0,8)='32100254'
      

  5.   

    不行啊,。索引也加了。还是很慢。是oracle数据库
      

  6.   

    这个语句不正确
    实际上我的语句应该这样:select * from D_JLX
    where  ZDBM in(select JLX from DZ_ZZXX where substr(JWZRQ,0,8)='32100254' group by JLX ) group by JLX 
      

  7.   

    单独执行下面这句效率也很差,不加group by 还好,一加就不行了select JLX from DZ_ZZXX where substr(JWZRQ,0,8)='32100254' group by JLX
      

  8.   

    D_JLX里面有3万多条数据
    DZ_ZZXX里面有2623430条数据。。
      

  9.   


    首先,我要告诉你,你这里group by JLX没有任何意义!!
    其次,substr(JWZRQ,0,8)='32100254' 这个操作本身也比较慢!!!
    再次,我上面给的是方法,具体应用有点小问题,你自己应该会改
      

  10.   


    select  distinct  d.* 
      from  D_JLX  d, DZ_ZZXX  x
     where  d.ZDBM = x.JLX
       and  substr(x.JWZRQ,0,8)='32100254'
      

  11.   

    select JLX from DZ_ZZXX 
    where JWZRQ like '32100254%' 
    group by JLXJWZRQ 加上索引
    JLX 加上索引
      

  12.   

    如果你索引添加都正确,
    下面这样应该就不错了。select * from D_JLX
     where  ZDBM in(select distinct JLX from DZ_ZZXX 
                     where substr(JWZRQ,0,8)='32100254')如果还嫌慢,那就只能优化你的表设计。
      

  13.   

    orderby groupby 的字段要建立索引啊。
      

  14.   

    或者select  d.* 
      from  D_JLX d,
           (select distinct JLX from DZ_ZZXX where substr(JWZRQ,0,8)='32100254') x
     where  d.ZDBM = x.JLX 
      

  15.   

    select a.* from D_JLX a
    inner join(select JLX from DZ_ZZXX where substr(JWZRQ,0,8)='32100254')b  on a.ZDBM=b.JLX  
      

  16.   

    select * from D_JLX
    where  ZDBM in(select JLX from DZ_ZZXX where substr(JWZRQ,0,8)='32100254')
    select * from D_JLX
     where  ZDBM in(select distinct JLX from DZ_ZZXX 
                     where substr(JWZRQ,0,8)='32100254')
    select  d.* 
      from  D_JLX d,
           (select distinct JLX from DZ_ZZXX where substr(JWZRQ,0,8)='32100254') x
     where  d.ZDBM = x.JLX 
    这3个语句运行起来时间都差不多,都要9s-10s
      

  17.   

    用inner join 代替 in 
      

  18.   

    再给你一个建议:
    可以考虑把JWZRQ字段的前8位提出来,
    单独建立一个带索引的字段,
    这样就可以不用substr
    速度理论上应该可以提高不少
      

  19.   

    将a.* 改为a.name ,a.xxx  
      

  20.   

    这个估计不行,表结构是固定的,就算能改, substr(JWZRQ,0,8)='32100254')实际上是
    substr(JWZRQ,0,length(参数))=参数)不确定
      

  21.   

    select a.* from D_JLX a
    inner join(select JLX from DZ_ZZXX where JWZRQ like '32100254%' )b  on a.ZDBM=b.JLX  不要用函数。那样不会用到索引。索引失效。用like 
      

  22.   

    like '32100254%' 用到索引like '%32100254%' 不用到索引
      

  23.   


    终于ok了,0.08s,为什么索引失效?
    还有谢谢foren_whb。。非常感谢
      

  24.   

    select Distinct D_JLX.* from D_JLX
    inner join DZ_ZZXX on D_JLX.ZDBM = DZ_ZZXX.JLX and DZ_ZZXX.JWZRQ like '32100254%' 
      

  25.   

    in和exists的区别与SQL执行效率in和exists的区别与SQL执行效率
    最近很多论坛又开始讨论in和exists的区别与SQL执行效率的问题,
    本文特整理一些in和exists的区别与SQL执行效率分析SQL中in可以分为三类:  1、形如select * from t1 where f1 in ('a','b'),应该和以下两种比较效率  select * from t1 where f1='a' or f1='b'  或者 select * from t1 where f1 ='a' union all select * from t1 f1='b'  你可能指的不是这一类,这里不做讨论。  2、形如select * from t1 where f1 in (select f1 from t2 where t2.fx='x'),  其中子查询的where里的条件不受外层查询的影响,这类查询一般情况下,自动优化会转成exist语句,也就是效率和exist一样。  3、形如select * from t1 where f1 in (select f1 from t2 where t2.fx=t1.fx),  其中子查询的where里的条件受外层查询的影响,这类查询的效率要看相关条件涉及的字段的索引情况和数据量多少,一般认为效率不如exists。  除了第一类in语句都是可以转化成exists 语句的SQL,一般编程习惯应该是用exists而不用in,而很少去考虑in和exists的执行效率.in和exists的SQL执行效率分析  A,B两个表,  (1)当只显示一个表的数据如A,关系条件只一个如ID时,使用IN更快:  select * from A where id in (select id from B)  (2)当只显示一个表的数据如A,关系条件不只一个如ID,col1时,使用IN就不方便了,可以使用EXISTS:  select * from A  where exists (select 1 from B where id = A.id and col1 = A.col1)  (3)当只显示两个表的数据时,使用IN,EXISTS都不合适,要使用连接:  select * from A left join B on id = A.id  所以使用何种方式,要根据要求来定。  这是一般情况下做的测试:  这是偶的测试结果:  set statistics io on 
      select * from sysobjects where exists (select 1 from syscolumns where id=syscolumns.id) 
      select * from sysobjects where id in (select id from syscolumns ) 
      set statistics io off  (47 行受影响)  表'syscolpars'。扫描计数 1,逻辑读取 3 次,物理读取 0 次,预读 2 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。  表'sysschobjs'。扫描计数 1,逻辑读取 3 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。  (1 行受影响)  (44 行受影响)  表'syscolpars'。扫描计数 47,逻辑读取 97 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。  表'sysschobjs'。扫描计数 1,逻辑读取 3 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。  (1 行受影响)  set statistics io on 
      select * from syscolumns where exists (select 1 from sysobjects where id=syscolumns.id) 
      select * from syscolumns where id in (select id from sysobjects ) 
      set statistics io off 
      (419 行受影响)  表'syscolpars'。扫描计数 1,逻辑读取 10 次,物理读取 0 次,预读 15 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。  表'sysschobjs'。扫描计数 1,逻辑读取 3 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。  (1 行受影响)  (419 行受影响)  表'syscolpars'。扫描计数 1,逻辑读取 10 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。  表'sysschobjs'。扫描计数 1,逻辑读取 3 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。  (1 行受影响)  测试结果(总体来讲exists比in的效率高):  效率:条件因素的索引是非常关键的  把syscolumns 作为条件:syscolumns 数据大于sysobjects  用in  扫描计数 47,逻辑读取 97 次,  用exists  扫描计数 1,逻辑读取 3 次  把sysobjects作为条件:sysobjects的数据少于syscolumns  exists比in多预读 15 次
      对此我记得还做过如下测试:  表  test  结构  id int identity(1,1), --id主键自增  sort int, --类别,每一千条数据为一个类别  sid int --分类id  插入600w条数据  如果要查询每个类别的最大sid 的话  select * from test a 
      where not exists(select 1 from test where sort = a.sort and sid > a.sid)
      比
      select * from test a 
      where sid in (select max(sid) from test where sort = a.sort)
      的执行效率要高三倍以上。具体的执行时间忘记了。但是结果我记得很清楚。在此之前我一直推崇第二种写法,后来就改第一种了。
    in和exists的sql执行效率分析,再简单举一个例子:
    declare @t table(id int identity(1,1), v varchar(10))
    insert @t select'a'
    union all select'b'
    union all select'c'
    union all select'd'
    union all select'e'
    union all select'b'
    union all select'c'
    --a语句in的sql写法
    select * from @t where v in (select v from @t group by v having count(*)>1)
    --b语句exists的sql写法
    select * from @t a where exists(select 1 from @t where id!=a.id and v=a.v)
      两条语句功能都是找到表变量@t中,v含有重复值的记录.  第一条sql语句使用in,但子查询中与外部没有连系.  第二条sql语句使用exists,但子查询中与外部有连系.  大家看SQL查询计划,很清楚了.  selec v from @t group by v having count(*)> 1  这条Sql语句,它的执行不依赖于主查询主句(我也不知道怎么来描述in外面的和里面的,暂且这么叫吧,大家明白就行)  那么,SQL在查询时就会优化,即将它的结果集缓存起来  即缓存了  v  ---  b  c  后续的操作,主查询在每处理一步时,相当于在处理 where v in('b','c') 当然,语句不会这么转化, 只是为了说明意思,也即主查询每处理一行(记为currentROW时,子查询不会再扫描表, 只会与缓存的结果进行匹配  而  select 1 from @t where id!=a.id and v=a.v  这一句,它的执行结果依赖于主查询中的每一行.  当处理主查询第一行时 即 currentROW(id=1)时, 子查询再次被执行 select 1 from @t where id!=1 and v='a' 扫描全表,从第一行记 currentSubROW(id=1) 开始扫描,id相同,过滤,子查询行下移,currentSubROW(id=2)继续,id不同,但v值不匹配,子查询行继续下移...直到currentSubROW(id=7)没找到匹配的, 子查询处理结束,第一行currentROW(id=1)被过滤,主查询记录行下移  处理第二行时,currentROW(id=2), 子查询 select 1 from @t where id!=2 and v='b' ,第一行currentSubROW(id=1)v值不匹配,子查询下移,第二行,id相同过滤,第三行,...到第六行,id不同,v值匹配, 找到匹配结果,即返回,不再往下处理记录. 主查询下移.  处理第三行时,以此类推...  sql优化中,使用in和exist? 主要是看你的筛选条件是在主查询上还是在子查询上。  通过分析,相信大家已经对in和exists的区别、in和exists的SQL执行效率有较清晰的了解。 
      

  26.   

    zzxap。
    额。。高手不好意思,分加错了
      

  27.   

    select * from D_JLX
    where exists (select JLX from DZ_ZZXX where D_JLX.ZDBM = DZ_ZZXX.JLX AND substr(JWZRQ,0,8)='32100254')
      

  28.   

    select Distinct D_JLX.* from D_JLX
    inner join DZ_ZZXX on D_JLX.ZDBM = DZ_ZZXX.JLX and DZ_ZZXX.JWZRQ like '32100254%' 
      

  29.   

    这是一SQL优化原则,对WHERE条件中的字段不能用函数,因为会造成index失效,像like前置不能用%号,要不index也会失效
      

  30.   

    create table ZZXX__temp as select JLX from DZ_ZZXX where substr(JWZRQ,0,8)='32100254';select * from D_JLX a where exists (select * from ZZXX__temp b where a.ZDBM=b.JLX)
    我保证你快。
      

  31.   

    小数据量查询使用in比使用union all方式效率高
    ---
    select * from dbo.BMS_IO20110701
    where tagid in(16842753,16842754,16842755,16842756,16908289,16908290,16908291,16908292,16908293,16908294)
    ---
    select * from dbo.BMS_IO20110701
    where 
    tagid =16842753
    union all
    select * from dbo.BMS_IO20110701
    where 
    tagid =16842754
    union all
    select * from dbo.BMS_IO20110701
    where 
    tagid =16842755
    union all
    select * from dbo.BMS_IO20110701
    where 
    tagid =16842756
    union all
    select * from dbo.BMS_IO20110701
    where 
    tagid =16908289
    union all
    select * from dbo.BMS_IO20110701
    where 
    tagid =16908290
    union all
    select * from dbo.BMS_IO20110701
    where 
    tagid =16908291
    union all
    select * from dbo.BMS_IO20110701
    where 
    tagid =16908292
    union all
    select * from dbo.BMS_IO20110701
    where 
    tagid =16908293
    union all
    select * from dbo.BMS_IO20110701
    where 
    tagid =16908294
      

  32.   

    补充上面的时间结果
    -----------------------------第一个SQL语句执行时间
    SQL Server 分析和编译时间: 
       CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。(74751 行受影响)
    表 'BMS_IO20110701'。扫描计数 3,逻辑读取 19245 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。(3 行受影响)SQL Server 执行时间:
       CPU 时间 = 1250 毫秒,占用时间 = 2048 毫秒。
    SQL Server 分析和编译时间: 
       CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。SQL Server 执行时间:
       CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。SQL Server 执行时间:
       CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。
    -----------------------------第二个SQL语句执行时间
    SQL Server 分析和编译时间: 
       CPU 时间 = 14 毫秒,占用时间 = 14 毫秒。(74751 行受影响)
    表 'BMS_IO20110701'。扫描计数 30,逻辑读取 192450 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。(22 行受影响)SQL Server 执行时间:
       CPU 时间 = 2703 毫秒,占用时间 = 2102 毫秒。
    SQL Server 分析和编译时间: 
       CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。SQL Server 执行时间:
       CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。SQL Server 执行时间:
       CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。