我在SQL Server中对视图运行了一个相当复杂的查询,其形式如下:
SELECT *
FROM myview, foo, bar
WHERE shared=1 AND [joins and other stuff]
ORDER BY sortcode;
如上所示的查询计划显示了在最终SELECT
之前的Sort
操作,这是我所期望的。只有35条匹配记录,查询耗时不到2秒。
但是如果我添加TOP 30
,查询几乎需要3分钟!使用SET ROWCOUNT
同样很慢。
查看查询计划,现在似乎是在连接和筛选器之前对myview
中的所有2+百万记录进行排序。
这种“排序”在查询计划上显示为对sortcode
索引的索引扫描,对主表的聚集索引查找,以及它们之间的嵌套循环,所有这些都在联接和筛选器之前。
在未指定** SORT
TOP
**,时,如何才能在TOP
之前强制SQL Server to ?
我不认为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
列上都有索引。
发布于 2011-06-09 22:17:27
于是,不幸的是,“试图智胜优化器(因为它并不总是知道得最好)”的游戏开始了。
您可以尝试将筛选部分放入子查询或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
。
https://stackoverflow.com/questions/6286837
复制相似问题