下面这个老大,系统其他查询的执行时间只是它的零头:
SELECT si.*,
FSndata.Pn,FSnData.Origin,FSnData.Status,FSnData.EndUser,FSnData.Cert,FSnData.BcLable,FSnData.BcDate1,FSnData.EndUser,FCustomer.GCode,
FPnInfo.Oem, FPnInfo.Weight,FPnInfo.Cube
FROM (SELECT ID,Sn,InfoDate,CaseNo,Item,CurrLvl,CurCond,Loc,Loc1,CurBcDate,Passed FROM FSnInfo WHERE (CaseNo=@'ABC8888') AND (Item=2))
si INNER JOIN FSndata ON si.Sn = FSndata.Sn INNER JOIN FPnInfo ON FSndata.Pn = FPnInfo.Pn LEFT JOIN FCustomer ON FCustomer.Sf=FSnData.EndUser ORDER BY si.Sn还有下面这个老二也够呛:
SELECT Sn,Pn,Origin,RLvl,Cond,Status,EndUser,Loc,Loc1,BcDate,Cert,BcLable
FROM FSndata WHERE (Pn='M01103') AND ((Cond IN ('NEW','RTD','WCS')) OR (Cond IS NULL)) AND ((Status IN ('ONW','OUT','RTD')) OR (Status IS NULL))
AND NOT EXISTS (SELECT ID FROM FSnInfo WHERE CaseNo='RS05042' AND Sn=FSnData.Sn)
ORDER BY 1

解决方案 »

  1.   

    在不太清楚其他细节的情况下,只看query有如小问题:
    1)si.*
    尽量避免在select里面使用'*'这样的东西,它会返回所以字段的值,如果不是必须的,最好只返回所需要的字段。如果返回的数据量很大的话,不仅在数据库内部要使用大量的内存和CPU进行排序和合并,在网络上也会有很多流量。
    2)在where中,诸如 IN, EXISTS都是不能被进行查询优化的,尽量少用或完全避免。
    3)对NULL值的判断是比较慢的,所以在记录中最好不要使用null值作为默认值或者空值。Cond = '', Cond = 0,会比Cond IS NULL 的判断快得多。然后,对于这类查询,一定要仔细看看表上的索引是否正确和有效。有时候加上一个正确的索引,查询速度可以提高几百倍以上。在查询密集型的应用中,索引是个非常关键的因素。最后,就算有索引,也要确保索引是更新的。过时的索引和统计数据也会导致查询速度明显降低。
      

  2.   

    回楼上:
    1)我那个si.*是返回子查询的别名中所有字段.既然已经在子查询中列出了所需字段,当然在主查询中就没必要再写一次了.
    2)如果不用IN或EXISTS,有什么更好的办法?
    3)NULL值确实很烦,但是数据库中的NULL值是无奈的,因为是外键,这里任何空串或0什么的都会违反规则.
      

  3.   

    不要用 'or' 'in' 'not exists' 这样的关键字
    因为这些关键字将不使用索引!
      

  4.   

    回2楼:
     in, exists有时候的确是很难避免,只能是尽量减少使用
    实在要用,也尽量在最小的记录集上使用
     对于null值在做外键的字段里面这种情况,我也不太确定,需要查一下资料你可以打开执行计划(execuation plan)
    仔细看一下你的query是如何被数据库引擎执行的,
    重点看那些花很多时间,很多CPU的部分,然后看在那里能不能加索引加索引是非常有效的一个方法例如,如下的where语句,就算你不能避免IN, EXISTS,
    也至少确保 Cond, Status上面建有索引,Pn也需要索引
    WHERE   (Pn= 'M01103 ')   AND   ((Cond   IN   ( 'NEW ', 'RTD ', 'WCS '))   OR   (Cond   IS   NULL))   AND   ((Status   IN   ( 'ONW ', 'OUT ', 'RTD '))   OR   (Status   IS   NULL)) 
      

  5.   

    To:w2jc 由于楼主的where条件中有or,in,即使加了索引也还是表扫描。
    我建议楼主可以在加了索引后,试着把语句改成union或者union all的形式
    第一个语句楼主可以把SELECT   ID,Sn,InfoDate,CaseNo,Item,CurrLvl,CurCond,Loc,Loc1,CurBcDate,Passed   FROM   FSnInfo   WHERE   (CaseNo=@ 'ABC8888 ')   AND   (Item=2)的where条件放到最后,同时在caseno上加非聚集索引,Sn上加聚集索引。
      

  6.   

    关于IN, EXISTS的效率问题,我看了一下最近的资料,尤其是mssql好像没有特意提到IN 和 exists在效率上的问题,但是他们特意提到 exists 比IN 的效率高一些。优化查询的关键还是要决定你的查询到底在什么地方花了最多的时间和I/O,然后才能考虑是什么方法。这两个链接比较好,教你如何生成和分析 query execution plan http://msdn2.microsoft.com/en-us/library/ms979196.aspx
    http://www.microsoft.com/technet/technetmag/issues/2007/11/SQLQuery/default.aspx (这个很长,但很深入)
    最重要的是要显示足够的信息,在生成 execution plan前使用如下语句:SET SHOWPLAN_ALL
    SET STATISTICS IO
    SET STATISTICS TIME
    SET STATISTICS PROFILE