查询优化。为什么TOAD这样做?

时间:2009-08-25 18:28:49

标签: tsql sql-server-2008 optimization

SQL Server 2008.我有这个非常大的查询,它的成本很高。 TOAD中包含查询调优功能,唯一的变化如下:

在:

LEFT OUTER JOIN (SELECT RIN_EXT.rejected, 
                               RIN_EXT.scar, 
                               RIN.fcreceiver, 
                               RIN.fcitemno 
                          FROM RCINSP_EXT RIN_EXT 
                               INNER JOIN dbo.rcinsp RIN 
                                  ON RIN_EXT.fkey_id = RIN.identity_column) RIN1 
         ON RCI.freceiver = RIN1.fcreceiver 
            AND RCI.fitemno = RIN1.fcitemno 
 WHERE RED.[YEAR] = '2009'

后:

LEFT OUTER JOIN (SELECT RIN_EXT.rejected, 
                               RIN_EXT.scar, 
                               RIN.fcreceiver, 
                               RIN.fcitemno 
                          FROM dbo.rcinsp RIN 
                               INNER JOIN RCINSP_EXT RIN_EXT 
                                  ON RIN.identity_column = COALESCE (RIN_EXT.fkey_id , RIN_EXT.fkey_id)) RIN1 
         ON RCI.freceiver = RIN1.fcreceiver 
            AND RCI.fitemno >= RIN1.fcitemno  -- ***** RIGHT HERE 
            AND RCI.fitemno <= RIN1.fcitemno
 WHERE RED.[YEAR] = '2009'

该字段是char(3)字段,这是SQL Server 2008.

知道他们为什么比我快得多?

3 个答案:

答案 0 :(得分:2)

看起来像一个升序索引搜索参数的东西 - 因为它添加了一个&gt; = - 我们没有看到你的查询的其余部分,但很明显还有关于RCI.fitemno的更多数据,它可以从中推断其余的查询。

这很奇怪:

        AND RCI.fitemno >= RIN1.fcitemno  -- ***** RIGHT HERE 
        AND RCI.fitemno <= RIN1.fcitemno

没有变成这个:

        AND RCI.fitemno = RIN1.fcitemno

因为它们是等价的。

答案 1 :(得分:2)

您未在“之前”查询中显示ON条件,因此我不知道TOAD已更改。但是,我会猜测发生了什么。

SQL Server查询优化程序使用成本估算来选择查询计划。成本估算基于行数估算。如果行数估计值不准确,优化程序可能不会选择最佳计划。

某些行数估算通常是准确的,就像具有统计信息的列的格式(列=值)一样。但是,如果列与外键约束无关,或者(表达式=值),表达式不是微不足道或涉及多个列,则只能猜测某些行计数估计值,如(column = othercolumn)

当统计信息不指导行数估计时,SQL Server使用通用估计值。如果将估计计划中的行数估计值与实际计划中的实际行计数进行比较,您有时可以看到问题并“欺骗”优化程序更改其行计数估算值。

如果使用AND添加不实际限制结果的谓词,如果优化程序无法识别它们是多余的,则可以降低行计数估计值。同样,如果使用OR添加谓词但实际上不会产生额外结果,则可以提高行数估计值。

也许这里的行数估计太高了,而额外的谓词正在纠正它们,从而导致对所考虑的计划的成本估算更好,并最终做出更好的计划选择。

答案 2 :(得分:2)

在查询中添加大于和小于查询是一个老技巧,有时会促使查询优化器在该列上使用索引。所以这个诀窍:

AND RCI.fitemno >= RIN1.fcitemno
AND RCI.fitemno <= RIN1.fcitemno

强制数据库使用RIN1和RCI fitemno列上的索引(如果存在)。我不确定当你这样做时是否会动态创建临时索引。

我曾经使用DB2数据库做这些技巧,并且它们运行良好。