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因此给它一个较低的要求,更容易在内存中分配)?有没有其他人目睹过这样的事情?
谢谢
表值函数可以具有非线性执行时间.
让我们考虑这个查询的等效函数:
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”添加到它时,它在不到一秒钟的时间内完成。事实证明,其中一张表上的聚集索引严重碎片化。
重建索引后,查询现在可以在不到一秒的时间内完成。