none
这个同样SQL 执行计划为何不一样 数据量不大啊就几千 查出结果也就 100多条 但是时间相差一个1秒一个10分钟不出来 RRS feed

  • 问题

  • 前提是同一台服务器 同一个数据库 无任何操作! 就跑同一个SQL
    语句是
    select CAST(0 as bit)
    checksta,'未发送' sta
    from
    (Select * from FKTransaction2 Where TransactionNO < LinkNO and LinkNO <> '' and delmark='0' )  a,
    (Select * from FKTransaction2 Where (LinkNO <> '' and delmark='0') and (LinkNO < TransactionNO)) b,
    FKCounterParty c
    where  a.TransactionNO=b.LinkNO  and a.direct like '%回购'  and  a.CounterParty=c.CounterPartyId and
    ((a.TradeDate>='20090526' and a.TradeDate <='20090526') or
    (b.TradeDate>='20090526' and b.TradeDate <='20090526')) and 
    a.account in (15,18,27,14,29,30,31,32,33,28,7,8,9,10,11,12,25,26,20,21,22,24) 

    快的执行计划是
     |--Compute Scalar(DEFINE:([Expr1011]=(0), [Expr1012]='未发送'))
          |--Hash Match(Inner Join, HASH:([FX_GF].[dbo].[FKTransaction2].[TransactionNO])=([FX_GF].[dbo].[FKTransaction2].[LinkNO]), RESIDUAL:([FX_GF].[dbo].[FKTransaction2].[TransactionNO]=[FX_GF].[dbo].[FKTransaction2].[LinkNO] AND ([FX_GF].[dbo].[FKTransaction2].[TradeDate]>'20090126' AND [FX_GF].[dbo].[FKTransaction2].[TradeDate] <='20091026' OR [FX_GF].[dbo].[FKTransaction2].[TradeDate]>'20090126' AND [FX_GF].[dbo].[FKTransaction2].[TradeDate] <='20091026')))
                |--Hash Match(Inner Join, HASH:([FX_GF].[dbo].[FKTransaction2].[CounterParty])=([c].[CounterPartyID]), RESIDUAL:([FX_GF].[dbo].[FKTransaction2].[CounterParty]=[FX_GF].[dbo].[FKCounterParty].[CounterPartyID] as [c].[CounterPartyID]))
                |    |--Filter(WHERE:([Expr1013]=(24) OR [Expr1013]=(22) OR [Expr1013]=(21) OR [Expr1013]=(20) OR [Expr1013]=(26) OR [Expr1013]=(25) OR [Expr1013]=(12) OR [Expr1013]=(11) OR [Expr1013]=(10) OR [Expr1013]=(9) OR [Expr1013]=(8) OR [Expr1013]=(7) OR [Expr1013]=(28) OR [Expr1013]=(33) OR [Expr1013]=(32) OR [Expr1013]=(31) OR [Expr1013]=(30) OR [Expr1013]=(29) OR [Expr1013]=(14) OR [Expr1013]=(27) OR [Expr1013]=(18) OR [Expr1013]=(15)))
                |    |    |--Compute Scalar(DEFINE:([Expr1013]=CONVERT_IMPLICIT(int,[FX_GF].[dbo].[FKTransaction2].[Account],0)))
                |    |        |--Table Scan(OBJECT:([FX_GF].[dbo].[FKTransaction2]), WHERE:([FX_GF].[dbo].[FKTransaction2].[Delmark]=(0) AND [FX_GF].[dbo].[FKTransaction2].[TransactionNO] <[FX_GF].[dbo].[FKTransaction2].[LinkNO] AND [FX_GF].[dbo].[FKTransaction2].[LinkNO] <>'' AND [FX_GF].[dbo].[FKTransaction2].[Direct] like '%回购'))
                |    |--Table Scan(OBJECT:([FX_GF].[dbo].[FKCounterParty] AS [c]))
                |--Table Scan(OBJECT:([FX_GF].[dbo].[FKTransaction2]), WHERE:([FX_GF].[dbo].[FKTransaction2].[Delmark]=(0) AND [FX_GF].[dbo].[FKTransaction2].[LinkNO] <[FX_GF].[dbo].[FKTransaction2].[TransactionNO] AND [FX_GF].[dbo].[FKTransaction2].[LinkNO] <>''))


    慢的执行计划是
    |--Compute Scalar(DEFINE:([Expr1011]=(0), [Expr1012]='未发送'))
          |--Merge Join(Inner Join, MANY-TO-MANY MERGE:([FX_GF].[dbo].[FKTransaction2].[CounterParty])=([c].[CounterPartyID]), RESIDUAL:([FX_GF].[dbo].[FKTransaction2].[CounterParty]=[FX_GF].[dbo].[FKCounterParty].[CounterPartyID] as [c].[CounterPartyID]))
                |--Nested Loops(Inner Join, WHERE:([FX_GF].[dbo].[FKTransaction2].[TransactionNO]=[FX_GF].[dbo].[FKTransaction2].[LinkNO] AND ([FX_GF].[dbo].[FKTransaction2].[TradeDate]='20090526' OR [FX_GF].[dbo].[FKTransaction2].[TradeDate]='20090526')))
                |    |--Sort(ORDER BY:([FX_GF].[dbo].[FKTransaction2].[CounterParty] ASC))
                |    |    |--Filter(WHERE:([Expr1013]=(24) OR [Expr1013]=(22) OR [Expr1013]=(21) OR [Expr1013]=(20) OR [Expr1013]=(26) OR [Expr1013]=(25) OR [Expr1013]=(12) OR [Expr1013]=(11) OR [Expr1013]=(10) OR [Expr1013]=(9) OR [Expr1013]=(8) OR [Expr1013]=(7) OR [Expr1013]=(28) OR [Expr1013]=(33) OR [Expr1013]=(32) OR [Expr1013]=(31) OR [Expr1013]=(30) OR [Expr1013]=(29) OR [Expr1013]=(14) OR [Expr1013]=(27) OR [Expr1013]=(18) OR [Expr1013]=(15)))
                |    |        |--Compute Scalar(DEFINE:([Expr1013]=CONVERT_IMPLICIT(int,[FX_GF].[dbo].[FKTransaction2].[Account],0)))
                |    |              |--Table Scan(OBJECT:([FX_GF].[dbo].[FKTransaction2]), WHERE:([FX_GF].[dbo].[FKTransaction2].[Delmark]=(0) AND [FX_GF].[dbo].[FKTransaction2].[TransactionNO] <[FX_GF].[dbo].[FKTransaction2].[LinkNO] AND [FX_GF].[dbo].[FKTransaction2].[LinkNO] <>'' AND [FX_GF].[dbo].[FKTransaction2].[Direct] like '%回购'))
                |    |--Table Scan(OBJECT:([FX_GF].[dbo].[FKTransaction2]), WHERE:([FX_GF].[dbo].[FKTransaction2].[Delmark]=(0) AND [FX_GF].[dbo].[FKTransaction2].[LinkNO] <[FX_GF].[dbo].[FKTransaction2].[TransactionNO] AND [FX_GF].[dbo].[FKTransaction2].[LinkNO] <>''))
                |--Sort(ORDER BY:([c].[CounterPartyID] ASC))
                    |--Table Scan(OBJECT:([FX_GF].[dbo].[FKCounterParty] AS [c])) 这个执行计划遥遥无期的
    请告诉我 原因 !怎么解决我会! 
    我想知道原因!
    要深入的说哦!
    高兴的石头 你遇到过没 ?
    CSDN 论坛我也问了
    2009年10月26日 8:52

答案

  •   好像是在CSDN看到过。
      SQL优化是基于成本的,它使用一些内部指标:内存、CPU利用率、I\O 及语句类型、表数据量、影响数据的分布、密度及可选择性、表上的索引、影响到的索引及列样本,然后再启发式的修剪生成计划。
      细细看你的计划 ,它使用Merge Join并且有排序的行为存在,Merge Join这种方式如果要进行排序,那种连接肯定是费时的,看你的计划根本没有使用索引,或优化器根本没有找到合适索引,显然这是种连接方式不适用于你的这个SQL查询 ,其实数据量很大并不是问题,如果能够从现有 B 树索引中获得预排序的所需数据,我以为合并联接通常应该是最快的可用联接算法,只是在你的这个查询里没有合适的B索引树而已。

    More: blog.csdn.net/happyflystone
    2009年11月5日 14:32

全部回复

  • 1.建议写sql时候不要用子查询,直接将所有条件写在外面。
    2.2个查询计划没看到一个index seek,都是table scan 建议增加索引。
    3.第二个慢的查询计划估计是 Nested Loops 导致,这个会搜索每一行。


    family as water
    2009年10月27日 1:55
  • 使用dbcc dbreindex把所有的索引 rebuild  一次
    2009年10月27日 4:41
  • 我不要解决方案!我要知道原因! 这些我都知道! 我奇怪的是为什么语句完全一样的 同一个数据库跑为何差别这么大! 解决我知道! 我要原因 我怀疑是MSSQL数据库的问题啊

    2009年10月27日 6:01
  • SQL Server的一个重要工作就是查询语句优化 (query optimization),然后根据选择的方案执行给出结果。

    查询优化是一个挺复杂的事情,和查询语句的书写方式,索引,数据分布,大小等都有关系。所以上面各位给你指出了一些解决方法。

    出现你这个问题的原因就是SQL Server在做查询优化的时候,没有足够的信息决定第一个计划要比第二个很好多。所以有时候做了错误的选择。这也就是为什么SQL Server提供query hints用于手动优化查询的原因。

    更多的关于查询优化的,可以参考BOL,或者其他说,例如Inside SQL Server 2005: Query Tunning and Optimization. 这本书英文,中文都有出版的。

    2009年11月5日 9:48
  •   好像是在CSDN看到过。
      SQL优化是基于成本的,它使用一些内部指标:内存、CPU利用率、I\O 及语句类型、表数据量、影响数据的分布、密度及可选择性、表上的索引、影响到的索引及列样本,然后再启发式的修剪生成计划。
      细细看你的计划 ,它使用Merge Join并且有排序的行为存在,Merge Join这种方式如果要进行排序,那种连接肯定是费时的,看你的计划根本没有使用索引,或优化器根本没有找到合适索引,显然这是种连接方式不适用于你的这个SQL查询 ,其实数据量很大并不是问题,如果能够从现有 B 树索引中获得预排序的所需数据,我以为合并联接通常应该是最快的可用联接算法,只是在你的这个查询里没有合适的B索引树而已。

    More: blog.csdn.net/happyflystone
    2009年11月5日 14:32
  • 问题就在这个Nested Loops上 如果A join B 是 AB行数相当 并且有排序是 merge join最快,其次hash join,最差的就是Nested loops

    Need for Speed
    2009年11月18日 2:40
  • 因为你没有足够的索引和统计信息,SQL Server无法估计join两边的行数,所以无法给出较优的执行计划。
    想不想时已是想,不如不想都不想。
    2009年11月18日 5:46
    版主
  • 我不要解决方案!我要知道原因! 这些我都知道! 我奇怪的是为什么语句完全一样的 同一个数据库跑为何差别这么大! 解决我知道! 我要原因 我怀疑是MSSQL数据库的问题啊


    如果sqlserver认为这两种方案差不多,就会随机选取。 主要是因为你的底层数据优化的不够,导致sqlserver无法判断出更好的查询方法。
    有dba的职位吗(北京的),请联系我 stswordman#hotmail.com
    2009年11月22日 3:06
    版主
  • 能把数据库放出来研究一下吗?
    2009年11月24日 4:10
  • 能把数据库放出来研究一下吗?
    • 已建议为答案 SQL STUDIO 2009年11月29日 4:42
    • 已编辑 SQL STUDIO 2009年11月29日 4:43 无效查询
    2009年11月29日 4:42
  • Table Scan 向查询计划图返回的结果集太多,有时候优化是根据索引计算的代价,未必是实时的。
    Sean Liu
    2009年11月30日 15:49