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

时间:2010-09-23 17:43:50

标签: sql sql-server sql-server-2008 performance

我似乎在SQL 2008中面临一个奇怪的问题。

我有一个查询,它可以从查询分析器中快速运行,但是如果通过存储过程运行则会超时! 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())

请注意,tbl1实际上是一个视图,其中col和col2是通过自联接来的。另外,根据业务需求,tbl2.col1需要具有连接值。如果需要解决这个问题,我可以修改我的观点。

2 个答案:

答案 0 :(得分:2)

作为一个副作用,请注意,如果你可以对字符串长度做一些假设,你的连接表达式可以简化(并且可能会获得更好的性能,因为一方现在使用相等):

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.col1数据实际存储在两列中。您通过在一列中放置两个不同的数据来违反第一个正常形式,现在,正如您所发现的那样,您在整个应用程序中就性能,开发和放大而付费。维护时间,查询复杂性等。

您甚至可以反转我的方案,以便LeftPart和RightPart列是真实的,并且您创建一个具有Col1名称的新计算列,其中包含一个索引,用于实现值并使它们可搜索。最后,如果绝对需要,您可以重命名表,使用旧名称在表上创建视图,然后在视图上放置INSTEAD-OF触发器以拦截对表的数据操作并将它们转换为正确的模式。 / p>

<强>更新

顺便说一句,如果你对表格设计有任何影响,你可能要考虑使用“99991231”的“开放结束日期”值或tbl2.date2而不是NULL。 Coalesce可以扼杀性能,有时在可能进行搜索时强制进行扫描。

答案 1 :(得分:1)

过去我遇到过由parameter sniffing引起的类似情况。您可以尝试上面文章中讨论的方法,看看它是否有所作为。

当您第一次运行存储过程时,SQL Server会缓存它的执行计划并将其用于未来。如果运行带有参数的存储过程使这个执行计划不是最佳的,那么你可以看到你所描述的行为。

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

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

This link针对参数嗅探问题找到了几个解决方案。