无论ORDER BY如何,SELECT TOP都很慢

时间:2011-06-09 00:31:57

标签: sql-server sql-server-2005 tsql sql-execution-plan query-hints

我在针对视图运行的SQL Server中有一个相当复杂的查询,格式为:

SELECT *
   FROM myview, foo, bar 
   WHERE shared=1 AND [joins and other stuff]
   ORDER BY sortcode;

如上所示的查询计划会在最终Sort之前显示SELECT操作,这正是我所期望的。只有35个匹配的记录,查询在2秒内完成。

但如果我添加TOP 30,查询大约需要3分钟!使用SET ROWCOUNT同样慢。

查看查询计划,它现在似乎在加入和过滤之前对myview 中的所有200多万条记录进行排序。

此“排序”在查询计划中显示为sortcode索引上的索引扫描,主表上的聚簇索引查找以及它们之间的嵌套循环,所有这些都在连接之前和过滤器。

如何在 SORT之前强制SQL Server TOP ,就像未指定TOP时那样?

我认为myview的构造不是问题,但为了以防万一,它是这样的:

CREATE VIEW myview AS
   SELECT columns..., sortcode, 0 as shared FROM mytable
   UNION ALL
   SELECT columns..., sortcode, 1 as shared FROM [anotherdb].dbo.mytable

本地mytable有几千条记录,同一MSSQL实例中另一个数据库中的mytable有几百条记录。两个表在各自的sortcode列上都有索引

1 个答案:

答案 0 :(得分:9)

因此开始了“试图超越优化器的不幸游戏(因为它并不总是最了解)”。

您可以尝试将过滤部分放入子查询或CTE中:

SELECT TOP 30 *
FROM
   (SELECT *
   FROM myview, foo, bar 
   WHERE shared=1 AND [joins and other stuff]) t
ORDER BY sortcode;

这可能足以强制它首先过滤(但优化器在每次发布时变得“更聪明”,并且有时可以看到这样的恶作剧)。或者您可能需要将此代码放入UDF。如果您将UDF编写为多语句表值函数,并在其中进行过滤,然后使用TOP x / ORDER BY查询该UDF,那么您很好地强制执行查询顺序(因为SQL Server)目前无法针对多语句UDF进行优化。)


当然,考虑到它,引入UDF只是隐藏我们真正做的事情的一种方式 - 创建临时表,使用一个查询来填充它(基于WHERE过滤器),然后另一个查询来查找来自临时表的TOP x