使用SELECT TOP x的SQL大量性能差异,即使x远高于所选行

Ray*_*Ray 15 sql t-sql sql-server performance user-defined-functions

我正在从表值函数中选择一些行,但是通过将SELECT TOP放在查询中,发现了一个莫名其妙的巨大性能差异.

SELECT   col1, col2, col3 etc
FROM     dbo.some_table_function
WHERE    col1 = @parameter
--ORDER BY col1
Run Code Online (Sandbox Code Playgroud)

需要花费5到6分钟才能完成.

然而

SELECT   TOP 6000 col1, col2, col3 etc
FROM     dbo.some_table_function
WHERE    col1 = @parameter
--ORDER BY col1
Run Code Online (Sandbox Code Playgroud)

在大约4或5秒内完成.

如果返回的数据集很大,这不会让我感到惊讶,但涉及的特定查询返回 200,000中的~5000行.

因此,在这两种情况下,整个表都被处理,因为SQL Server一直在搜索6000行,它将永远不会到达.为什么那么巨大的差异呢?这是否与SQL Server在预期结果集大小时分配空间的方式有关(TOP 6000因此给它一个较低的要求,更容易在内存中分配)?有没有其他人目睹过这样的事情?

谢谢

Qua*_*noi 8

表值函数可以具有非线性执行时间.

让我们考虑这个查询的等效函数:

SELECT  (
        SELECT  SUM(mi.value)
        FROM    mytable mi
        WHERE   mi.id <= mo.id
        )
FROM    mytable mo
ORDER BY
        mo.value
Run Code Online (Sandbox Code Playgroud)

此查询(计算运行SUM)在开始时较快,在结束时较慢,因为在mo它的每一行上应该总结所有前面的值,这需要重绕rowsource.

SUM随着行数增加,计算每行的时间增加.

如果你做得mytable足够大(比如100,000行,如你的例子中)并运行这个查询,你会发现它需要相当长的时间.

但是,如果您应用于TOP 5000此查询,您将看到它的完成速度比1/20完整表所需的时间快得多.

最有可能的是,你的情况也会发生类似的情况.

更确切地说,我需要看到函数定义.

更新:

SQL Server 可以将谓词推入函数中.

例如,我刚创建了这个TVF:

CREATE FUNCTION fn_test()
RETURNS TABLE
AS
RETURN  (
        SELECT  *
        FROM    master
        );
Run Code Online (Sandbox Code Playgroud)

这些查询:

SELECT  *
FROM    fn_test()
WHERE   name = @name

SELECT  TOP 1000 *
FROM    fn_test()
WHERE   name = @name
Run Code Online (Sandbox Code Playgroud)

产生不同的执行计划(第一个使用集群扫描,第二个使用索引搜索与a TOP)


小智 5

我遇到了同样的问题,连接五个表的简单查询需要两分钟才能完成,返回 1000 行。当我将“TOP 10000”添加到它时,它在不到一秒钟的时间内完成。事实证明,其中一张表上的聚集索引严重碎片化。

重建索引后,查询现在可以在不到一秒的时间内完成。