SELECT *   
   FROM commodity_info,commodity
   WHERE ( commodity_info.COM_ID = commodity.COM_ID )  
 and (
(commodity.com_code like '%b000002%') 
or 
(
commodity_info.com_id in (select commodity_info.down_comid from commodity,commodity_info where commodity.com_id=commodity_info.com_id and commodity.com_code like '%b000002%') 
)
)
  SELECT *   
   FROM commodity_info,commodity
   WHERE ( commodity_info.COM_ID = commodity.COM_ID )  
 and (
(commodity.com_code like '%b000002%') 
or 
(
commodity.com_id in (select commodity_info.down_comid from commodity,commodity_info where commodity.com_id=commodity_info.com_id and commodity.com_code like '%b000002%') 
)
)这两条语句的区别是 or后表名不同,其他的地方都一样。
他们的执行效果差别很大,第一条,两分钟,第二条,1秒钟。
查看执行计划后发现,第一条是没有使用索引IX_COM_COMCODE,而是使用的聚集索引PK_COMMODITY。
那位高手能帮忙解释一下为什么?

解决方案 »

  1.   

    因为commodity_info.COM_ID = commodity.COM_ID,
    所以下边的条件,用commodity_info.COM_ID 和commodity.COM_ID是一样的。
      

  2.   

    第二条之所以会快就是因为对commodity使用了聚焦索引
      

  3.   

    commodity和commodity_info相当于一对一关系的表格,行数都是9000多。
    commodity中com_id是主键,com_code有索引,非聚集非唯一的。
    commodity_info中com_id和mod_id是主键,com_id是commodity的外键。
      

  4.   

    commodity_info.com_id这个是详细表?
    com_id是什么个情况?commodity.com_id 又是什么个情况。
    从执行计划来看第一个是两个表join 在串联 后面的or条件第二个是对表commodity赛选之后 和commodity_info 进行join这样的话第二个当然是大优了
      

  5.   

    LZ 居然能写出这样的sql语句
    简直就是一朵奇葩
      

  6.   

    你这个和SELECT *   
      FROM commodity_info,commodity
      WHERE ( commodity_info.COM_ID = commodity.COM_ID )   
     and commodity.com_code like '%b000002%'的结果是一样的啊  
      

  7.   

    那个or 是多此一举,还导致sql 生成了一段很复杂的执行计划。
      

  8.   

    还不如这样
    SELECT *   
    FROM commodity_info
    INNER JOIN  commodity
    WHERE commodity_info.COM_ID = commodity.COM_ID  
     AND commodity.com_code like '%b000002%'
      

  9.   

    感觉LZ应该只是想作个测试吧,要不不可能写出这么低级的SQL语句
      

  10.   

    怎么没有区别了
    你写的是ANSI SQL-89的写法,只支持内连接,交叉连接
    我写的是ANSI SQL-92的写法,支持内连接,外连接,交叉连接
      

  11.   

    是否可以理解为,因为第二条语句中的条件都是commodity表中的字段,
    所以就IN中的条件和(commodity.com_code like '%b000002%') 一块处理啦,
    然后再和commodity_info 进行inner join呀?因为第一条语句的条件,既有commodity表的字段,也有commodity_info表的字段,
    所以,首先,commodity和commodity_info两个表合并,取出commodity_info.com_id和commodity.com_code,然后再对应下边这两个字段的条件进行处理吗??
      

  12.   

    注意一下,IN中取出来的值是down_comid,抱歉,刚才讲表结构的时候,忘记这个字段啦,他表示该COM_ID的下级COM_ID,大包装商品的对应的小包装商品。
      

  13.   

    如果照着10楼的思路走,第一条慢的原因是在对commodity和commodity_info未加条件的聚集索引扫描上。
    图片右边显示不全,不知道怎么回事
      

  14.   

    不要使用in,把它改成exists
    SELECT * FROM commodity_info,commodity
    WHERE ( commodity_info.COM_ID = commodity.COM_ID )   
    and ((commodity.com_code like '%b000002%')  
    or(exists(select 1 from commodity a,commodity_info b 
      where a.com_id=b.com_id 
      and a.com_code like '%b000002%'
      and b.down_comid=commodity_info.com_id)))--------------------------------------------------------------
    SELECT * FROM commodity_info,commodity
    WHERE ( commodity_info.COM_ID = commodity.COM_ID )   
    and ((commodity.com_code like '%b000002%')  
    or(exists(select 1 from commodity a,commodity_info b 
      where a.com_id=b.com_id 
      and a.com_code like '%b000002%'
      and b.down_comid=commodity.com_id))
      

  15.   


    改成exists后,执行速度和执行计划和原来一样,下班了,先回家
      

  16.   


    还有为什么它不使用索引IX_COM_COMCODE?
      

  17.   

    还有为什么它不使用索引IX_COM_COMCODE?
    顶一下
      

  18.   

    commodity.com_id,不是主见是吧?而那张表的是主键,是吧?
      

  19.   

    commodity和commodity_info相当于一对一关系的表格,行数都是9000多。
    commodity中com_id是主键,com_code有索引,非聚集非唯一的。
    commodity_info中com_id和mod_id是主键,com_id是commodity的外键,down_comid,表示该COM_ID的下级COM_ID,大包装商品的对应的小包装商品。