Sql server T-SQL SELECT*快,SELECT TOP 50慢

Sql server T-SQL SELECT*快,SELECT TOP 50慢,sql-server,tsql,Sql Server,Tsql,删除了以前的帖子,可能是问的方法不对,我会再试一次 -- 300Ms SELECT AppId FROM Application ap LEFT OUTER JOIN MissingThings mt on mt.AppId = ap.AppId WHERE mt.AppId is NULL ORDER BY mt.Id -- 1.5s SELECT TOP 50 FROM (TheSame) -- 100Ms SELECT TOP 5

删除了以前的帖子,可能是问的方法不对,我会再试一次

    -- 300Ms
    SELECT AppId FROM Application ap
    LEFT OUTER JOIN MissingThings mt on mt.AppId = ap.AppId
    WHERE mt.AppId is NULL
    ORDER BY mt.Id

-- 1.5s
SELECT TOP 50 FROM (TheSame)

    -- 100Ms
    SELECT TOP 50 AppId FROM Application ap
    LEFT OUTER JOIN MissingThings mt on mt.AppId = ap.AppId
    --WHERE mt.AppId is NULL
    ORDER BY mt.Id 
如果我对原始查询应用TOP,它会变慢。如果没有TOP,它将快速返回所有1000条记录

如果我删除WHERE子句并获得前50名,它又快了

正如其他帖子建议的那样,也尝试用“不存在”替换WHERE。没有帮助

是否有任何一般可能的原因,或它确实是特定于我的数据库? 如果它是具体的,我想,我不能期望在这里得到帮助,因为我不允许分享执行计划

编辑:

WHERE子句中还有另外两个条件,我认为它们确实可以忽略,但一旦我对它们进行了注释,原始查询将在50ms内返回

SELECT TOP 50 AppId FROM Application ap
        LEFT OUTER JOIN MissingThings mt on mt.AppId = ap.AppId
        WHERE mt.AppId is NULL
AND ap.IsOrderFinished = 1
AND ap.IsAssigned = 2
        ORDER BY mt.Id 
在IsOrderFinished和IsAssigned上添加了非聚集索引-这两个或其中一个索引都没有帮助

更多结果:

降序速度为50毫秒!
按mt.Id DESC go figure排序有时我无法将工作优化为完整查询,但我可以对其部分进行优化。然后,我不再继续尝试优化完整查询,而是将部分移动到一个时态表中,并使用它们来构造完整查询

这应该在300ms而不是1.5s内执行

SELECT AppId 
into #Application
FROM Application ap
     LEFT OUTER JOIN MissingThings mt on mt.AppId = ap.AppId
WHERE mt.AppId is NULL
ORDER BY ap.AppId 

SELECT TOP 50 * FROM #Application

DROP TABLE #Application
我们也会尝试使用最快的查询来加快速度。这将在接近100毫秒的时间内执行

CREATE TABLE #Application (AppId INT, MissingAppId INT)
CREATE CLUSTERED INDEX #IX_Application ON #Application (MissingAppId, AppId)

INSERT INTO #Application (AppId, MissingAppId)
SELECT ap.AppId, mt.AppId
FROM Application ap
     LEFT OUTER JOIN MissingThings mt on mt.AppId = ap.AppId

SELECT TOP 50 * 
FROM #Application
WHERE MissingAppId IS NULL
ORDER BY AppId

DROP TABLE #Application

你们在表格应用程序上有什么索引?是否有AppId列的专用索引?AppId是PKey,并且是应用程序表上的聚集索引。这可能是由于过时的统计信息导致基数不匹配造成的问题,但只有执行计划才能确认这一点。如果你不能分享他们,即使在匿名所有的名字?这变得很困难。无论如何,更新这两个表的统计数据都不会有什么坏处。如果不是这样的话,indexing Missingtings.AppId也不会这样做。首先,我建议更改where子句,以便在表的PKey@lakta,我只需要获取在该联接中不匹配的记录。如果我在PKey上这样做,它将不会返回任何结果?或者我错过了什么。所以AppId总是在主表上,但是在第二个表中过滤没有相应记录的记录。好主意。我正在考虑一种方法来提取所有数据,然后执行排序、排序……让我们看看这是否有帮助。@st_stefanov让我知道它是否有效,因为如果有效,我们可以使用相同的原理尝试在最快的100毫秒查询上运行它。@st_stefanov drop应用程序必须是drop table应用程序。我已经更新了答案。您的意思是说,还是有其他错误?在这种情况下,请共享错误消息。我有一些问题来适应嵌套的select,但我使用select*从MyViewName导入了TENTRABLE…这很有效。速度很快,但需要600毫秒300ms@st_stefanov:视图无法创建临时表或具体化其他视图。为此,您需要一个存储过程。或者,如果选项FORCE ORDER阻止优化器以次优方式扩展联接,您可以尝试,尽管这样的提示应该作为最后手段使用。请注意,添加分页本身会增加另一种方式,使事情变得缓慢,因为分页这些结果本身就是低效的。Skip1000.Take50基本上仍然会使服务器在获得下一个50行之前生成1000行要忽略的行。