在查询语句结尾加上"option(force order)"试试.

解决方案 »

  1.   

    SELECT ...
    FROM (select * from t0 WHERE t0.f1 IN (1, 2, 3, 4))
    t0
      INNER JOIN   
    t1 ON (t0.f1 = t1.f1)
      INNER JOIN   
    t2 ON (t1.f2 = t2.f2)
      INNER JOIN   
    t3 ON (t2.f3 = t3.f3)试试这个
      

  2.   

    把语句改成这样试试呢,这两个语句是等价的:SELECT ...
    FROM 
    t0
      INNER JOIN   
    t1 ON (t0.f1 = t1.f1) and t0.f1 IN (1, 2, 3, 4)
      INNER JOIN   
    t2 ON (t1.f2 = t2.f2)
      INNER JOIN   
    t3 ON (t2.f3 = t3.f3)
      

  3.   

    另外,这个也不是bug,只能说明,sql server产生了不同的执行计划,这个时候,我们要么加上hint,要么就尝试修改一下语句,看看执行计划是否会改变,如果变了,并且性能上升了,那就说明我们改对了
      

  4.   

    另外,像上面说的,可以考虑更新一下统计信息,比如:update statistics t0update statistics t1update statistics t2update statistics t3
      

  5.   

    --不知道楼主的表上的索引时如何建的,有(非聚集)索引的话,大概是这个计划你说为的小表按1000条数据算,大表按50W数据算(也不是说50W就打了,主要是数据再多了测试时间太久,不方便)|---select * from   t1 inner join t2 on t1.id=t2.id   inner join t3 on t2.id=t3.id  where t1.id in (1,100,900,100)
      |--Nested Loops(Inner Join, OUTER REFERENCES:([Bmk1004]))
       |--Nested Loops(Inner Join, OUTER REFERENCES:([DBTest].[dbo].[t3].[id]))
       |    |--Nested Loops(Inner Join, OUTER REFERENCES:([Bmk1008]))
       |    |    |--Nested Loops(Inner Join, OUTER REFERENCES:([DBTest].[dbo].[t1].[id]))
       |    |    |    |--Nested Loops(Inner Join, OUTER REFERENCES:([Bmk1000]))
       |    |    |    |    |--Index Seek(OBJECT:([DBTest].[dbo].[t1].[index_t1id]), SEEK:([DBTest].[dbo].[t1].[id]=(1) OR [DBTest].[dbo].[t1].[id]=(100) OR [DBTest].[dbo].[t1].[id]=(900)) ORDERED FORWARD)
       |    |    |    |    |--RID Lookup(OBJECT:([DBTest].[dbo].[t1]), SEEK:([Bmk1000]=[Bmk1000]) LOOKUP ORDERED FORWARD)
       |    |    |    |--Index Seek(OBJECT:([DBTest].[dbo].[t3].[index_t3id]), SEEK:([DBTest].[dbo].[t3].[id]=[DBTest].[dbo].[t1].[id]),  WHERE:([DBTest].[dbo].[t3].[id]>=(1) AND [DBTest].[dbo].[t3].[id]<=(900)) ORDERED FORWARD)
       |    |    |--RID Lookup(OBJECT:([DBTest].[dbo].[t3]), SEEK:([Bmk1008]=[Bmk1008]) LOOKUP ORDERED FORWARD)
       |    |--Index Seek(OBJECT:([DBTest].[dbo].[t2].[index_t2id]), SEEK:([DBTest].[dbo].[t2].[id]=[DBTest].[dbo].[t3].[id]),  WHERE:([DBTest].[dbo].[t2].[id]>=(1) AND [DBTest].[dbo].[t2].[id]<=(900)) ORDERED FORWARD)
       |--RID Lookup(OBJECT:([DBTest].[dbo].[t2]), SEEK:([Bmk1004]=[Bmk1004]) LOOKUP ORDERED FORWARD)
      

  6.   

    这个起作用这个也起作用不过如果频繁更新统计信息,估计会对查询性能有影响,不知道怎么确定什么时候更新统计信息。

    统计更新的时机,
    1.数据库AUTO_CREATE_STATISTICS选项=ON时,自动更新.2.手动更新1: 
    update statistics [表名] with FULLSCAN --全表扫描.
    update statistics [表名] with SAMPLE [百分比] PERCENT --按百分比抽样更新统计.
    update statistics [表名] with SAMPLE [行数] ROWS --按指定行数抽样更新统计.
    参考 http://technet.microsoft.com/zh-cn/library/ms187348.aspx3.手动更新2: sp_updatestats 全部更新,默认选择抽样更新.判断是否需手工更新统计的时机,
    1.数据仓库中,大量导入数据后,平时无DML变更,需更新.
    2.执行计划中,Rows与EstimateRows差距较大的情况.
    3.以下SQL语法中,rowmodctr(未更新统计的记录数)较大的情况.
      select object_name(a.object_id) 'table_name',a.name 'stats_name', c.name 'col_name',e.rowcnt,e.rowmodctr,
      case when auto_created=1 then 'auto_created' when user_created=1 then 'user_created' when e.rowcnt>0 then 'index_col' end stype
      from sys.stats a
      inner join sys.stats_columns b on a.object_id=b.object_id and a.stats_id=b.stats_id and b.stats_column_id=1
      inner join sys.columns c on b.object_id=c.object_id and b.column_id=c.column_id
      inner join sysobjects d on a.object_id=d.id and d.xtype='U'
      inner join sysindexes e on a.object_id=e.id and a.name=e.name and e.name is not null
      order by a.object_id
      

  7.   

    針對這種情況,可以直接指定某一個索引來解決:with(index( indexName ))E.g.select .... from tableName1 with(index(IndexName))  join tableName_2 with(index(IndexName)) on ....
      

  8.   

            在计划中,优化器负责决定査询以什么顺序来访问表、使用哪些索引和应用什么样的访问方法、使用哪种联接算法等等。实际上,对于给定的査询,优化器会评估多个执行计划,并从生成的多个计划中选择一个开销最低的计划。注意,SQL Server可能不会为给定的査询生成所有可能的执行计划。如果总是要生成所有的执行计划,那么优化过程可能会太长。 SQL Server将根据一些因素(如查询所涉及到的表的长度)来计算优化过程的临界值。一种临界值是基于时间的,SQL Server不会在优化上花费比该时间临界值更长的时间。还有一种临界值是基于开销的,也就是说,如果找到一个开销比该临界值更低的计划,就认为这个计划“足够好”,这时就会停止优化,并使用该计划。另外还有执行计划缓存和查询优化器之间的矛盾
            查询优化器希望尽可能选择高效的执行计划,而执行计划缓存却希望尽可能的重用缓存,这两种机制在某些情况会产生冲突。