代码之家  ›  专栏  ›  技术社区  ›  Saurabh Kumar

查询在SP中超时,但在查询分析器中运行正常

  •  1
  • Saurabh Kumar  · 技术社区  · 15 年前

    我有一个查询,它在查询分析器中运行得又好又快,但是如果运行存储过程,它就会超时!SP只是从这个查询开始,在这个查询之前没有其他代码

    SELECT col1,col2 FROM TBL1 (nolock)
    INNER JOIN TBL2 (nolock) 
    ON tbl1.col=LEFT(tbl2.col1,LEN(tbl2.col1)-2) AND tbl1.col2=RIGHT(tbl2.col1,2)
    AND tbl1.col4=2233
    AND tbl1.date1 BETWEEN tbl2.date1 and isnull(tbl2.date2,getdate())
    

    2 回复  |  直到 15 年前
        1
  •  2
  •   momo    15 年前

    另一个问题是,请注意,如果可以对字符串长度进行一些假设,那么可以简化联接表达式(并且可能会获得更好的性能,因为有一方现在正在使用等式):

    SELECT tbl1.col1, tbl1.col2
    FROM
       TBL1
       INNER JOIN TBL2
    
          ON tbl1.col + tbl1.col2 = tbl2.col1
          AND tbl1.col4=2233
          AND tbl1.date1 BETWEEN tbl2.date1 AND Coalesce(tbl2.date2, GetDate())
    

    此外,如果您希望获得最佳性能,请尝试以下方法:

    ALTER TABLE TBL2 ADD LeftPart AS (LEFT(col1, LEN(col1)-2));
    ALTER TABLE TBL2 ADD RightPart AS (RIGHT(tbl2.col1,2));
    CREATE NONCLUSTERED INDEX IX_TBL2_Parts ON TBL2 (LeftPart, RightPart);
    

    SELECT tbl1.col1, tbl1.col2
    FROM
       TBL1
       INNER JOIN TBL2
          ON tbl1.col = tbl2.LeftPart
          AND tbl1.col2 = tbl2.RightPart
          AND tbl1.col4=2233
          AND tbl1.date1 BETWEEN tbl2.date1 AND Coalesce(tbl2.date2, GetDate())
    

    更好

    更新

    顺便说一下,如果您对表设计有任何影响,您可能需要考虑对tbl2.date2使用“openended date”值'99991231'或类似值,而不是空值。这种合并可能会破坏性能,有时会在可能进行寻道时强制执行扫描。

        2
  •  1
  •   Abe Miessler    15 年前

    parameter sniffing . 您可以尝试上面文章中讨论的方法,看看它是否有帮助。

    当您第一次运行存储过程时,SQLServer会缓存它的执行计划并继续使用它。如果使用使此执行计划不是最佳的参数运行存储过程,则可以看到所描述的行为。

    您还可以使用查询提示 recompile 确保每次执行时都使用新的执行计划。为此,您可以添加 OPTION(RECOMPILE)

    SELECT id, name 
    from tableName
    WHERE id between @min and @max
    OPTION(RECOMPILE);
    

    This link 讨论了参数嗅探问题的几种解决方案。