单返回值的表值函数与标量值函数 [英] Table Valued Function vs Scalar Values Function for single return Value

查看:38
本文介绍了单返回值的表值函数与标量值函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我从缩放函数返回单个值,如下所示:

I am returning single value from a scaler function as below:

CREATE FUNCTION [dbo].[GetNoOfAssignedCases]
(
    @UserID INT,
    @FromD DATETIME,
    @ToD DATETIME
)
RETURNS NVARCHAR(MAX)
AS
BEGIN
    DECLARE @CaseCount INT = 0
    SELECT @CaseCount = COUNT(1) FROM Cases
    WHERE 
        CaseAssignedToAssessor = @UserID AND 
        CAST(ActionDateTime AS DATE) >= @FromD AND
        CAST(ActionDateTime AS DATE) <= @ToD
    RETURN @CaseCount
END

并使用它如下:

SELECT [Name], [DBO].[GetNoOfAssignedCases](UserID, GETDATE()-30, GETDATE()) FROM Users

可以用表值函数代替吗?它会对性能产生任何影响吗?哪个会更快?

Can it be replace with table valued function? And will it have any performance impact? Which will be faster?

推荐答案

我与 Jonatha Dickinson 的讨论(看看他的回答)让我做了一些快速测试:

My discussion with Jonatha Dickinson (look at his answer) brought me to do some quick tests:

结果表明,纯嵌入式标量子选择并没有那么糟糕.查询仅一个值,它甚至是最快的.正如预期的那样,标量函数很糟糕.TVF 返回的字段越多,相对性能增益就越好.

It comes out, that the pure,embedded scalar sub-select is not that bad. Querying just one value it's even the fastest. As expected the Scalar Function is bad. The more fields are given back by the TVF the better is the relativ performance gain.

唯一确定的答案是:标量函数是最糟糕的并且多行 TVF - 大多数情况下 - 比内联慢.任何临时方法往往会更快.

The only sure answer is: The scalar function is the worst and a multi-line TVF is - most of the time - slower than inline. Any ad-hoc approach tends to be faster.

但我可以为所有情况设置特殊情况(标量函数除外),其中一种方法是最快的.

But I could set up special cases to all situations (except the scalar function), where one approach was the fastest.

结论:(一如既往:-))这取决于...

Conclusion: (as always :-) ) It depends...

提示:最好让这与包含许多表和列的大型数据库发生冲突.

Hint: Best is to let this go against a big database with many tables and columns.

CREATE FUNCTION dbo.CountColumnScalar(@TableSchema AS VARCHAR(100),@TableName AS VARCHAR(100))
RETURNS INT
AS
BEGIN
    RETURN(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS AS c WHERE c.TABLE_SCHEMA=@TableSchema AND c.TABLE_NAME=@TableName);
END
GO
CREATE FUNCTION dbo.CountConstraintScalar(@TableSchema AS VARCHAR(100),@TableName AS VARCHAR(100))
RETURNS INT
AS
BEGIN
    RETURN(SELECT COUNT(*) FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS c WHERE c.TABLE_SCHEMA=@TableSchema AND c.TABLE_NAME=@TableName);
END
GO

CREATE FUNCTION dbo.CountAllTVF(@TableSchema AS VARCHAR(100),@TableName AS VARCHAR(100))
RETURNS TABLE
RETURN SELECT (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS AS c WHERE c.TABLE_SCHEMA=@TableSchema AND c.TABLE_NAME=@TableName GROUP BY c.TABLE_SCHEMA,c.TABLE_NAME) AS ColCounter
             ,(SELECT COUNT(*) FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS c WHERE c.TABLE_SCHEMA=@TableSchema AND c.TABLE_NAME=@TableName GROUP BY c.TABLE_SCHEMA,c.TABLE_NAME) AS ConstraintCounter    ;
GO
CREATE FUNCTION dbo.CountAllTVF_multiline(@TableSchema AS VARCHAR(100),@TableName AS VARCHAR(100))
RETURNS @tbl TABLE (ColCounter INT,ConstraintCounter INT)
AS
BEGIN
INSERT INTO @tbl
SELECT (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS AS c WHERE c.TABLE_SCHEMA=@TableSchema AND c.TABLE_NAME=@TableName GROUP BY c.TABLE_SCHEMA,c.TABLE_NAME) AS ColCounter
      ,(SELECT COUNT(*) FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS c WHERE c.TABLE_SCHEMA=@TableSchema AND c.TABLE_NAME=@TableName GROUP BY c.TABLE_SCHEMA,c.TABLE_NAME) AS ConstraintCounter;
RETURN;
END
GO

DECLARE @time DATETIME=GETDATE();
SELECT TABLE_SCHEMA,TABLE_NAME
     ,(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS AS c WHERE c.TABLE_SCHEMA=t.TABLE_SCHEMA AND c.TABLE_NAME=t.TABLE_NAME ) AS ColCounter
     ,(SELECT COUNT(*) FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS c WHERE c.TABLE_SCHEMA=t.TABLE_SCHEMA AND c.TABLE_NAME=t.TABLE_NAME ) AS ConstraintCounter
FROM INFORMATION_SCHEMA.TABLES AS t;
PRINT 'pure embedded scalar sub-select: ' + CAST(CAST(GETDATE()-@time AS TIME) AS VARCHAR(MAX)); SET @time=GETDATE();


SELECT TABLE_SCHEMA,TABLE_NAME
     ,dbo.CountColumnScalar(t.TABLE_SCHEMA,t.TABLE_NAME ) AS ColCounter 
     ,dbo.CountConstraintScalar(t.TABLE_SCHEMA,t.TABLE_NAME ) AS ConstraintCount 
FROM INFORMATION_SCHEMA.TABLES AS t
PRINT 'scalar function: ' + CAST(CAST(GETDATE()-@time AS TIME) AS VARCHAR(MAX)); SET @time=GETDATE();


SELECT t.TABLE_SCHEMA,t.TABLE_NAME
      ,colJoin.ColCount
      ,conJoin.ConstraintCount 
FROM INFORMATION_SCHEMA.TABLES AS t
INNER JOIN (SELECT COUNT(*) As ColCount,c.TABLE_SCHEMA,c.TABLE_NAME 
            FROM INFORMATION_SCHEMA.COLUMNS AS c 
            GROUP BY c.TABLE_SCHEMA,c.TABLE_NAME) AS colJoin ON  colJoin.TABLE_SCHEMA=t.TABLE_SCHEMA AND colJoin.TABLE_NAME=t.TABLE_NAME
INNER JOIN (SELECT COUNT(*) As ConstraintCount,c.TABLE_SCHEMA,c.TABLE_NAME 
            FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS c 
            GROUP BY c.TABLE_SCHEMA,c.TABLE_NAME) AS conJoin ON  conJoin.TABLE_SCHEMA=t.TABLE_SCHEMA AND conJoin.TABLE_NAME=t.TABLE_NAME
PRINT 'JOINs on sub-selects: ' + CAST(CAST(GETDATE()-@time AS TIME) AS VARCHAR(MAX)); SET @time=GETDATE();

SELECT t.TABLE_SCHEMA,t.TABLE_NAME
      ,ColCounter.*
FROM INFORMATION_SCHEMA.TABLES AS t
CROSS APPLY dbo.CountAllTVF(t.TABLE_SCHEMA,t.TABLE_NAME) AS ColCounter
PRINT 'TVF inline: ' + CAST(CAST(GETDATE()-@time AS TIME) AS VARCHAR(MAX)); SET @time=GETDATE();


SELECT t.TABLE_SCHEMA,t.TABLE_NAME
      ,ColCounter.*
FROM INFORMATION_SCHEMA.TABLES AS t
CROSS APPLY dbo.CountAllTVF_multiline(t.TABLE_SCHEMA,t.TABLE_NAME) AS ColCounter
PRINT 'TVF multiline: ' + CAST(CAST(GETDATE()-@time AS TIME) AS VARCHAR(MAX)); SET @time=GETDATE();
GO

DROP FUNCTION dbo.CountColumnScalar;
DROP FUNCTION dbo.CountAllTVF;
DROP FUNCTION dbo.CountAllTVF_multiline;
DROP FUNCTION dbo.CountConstraintScalar;

这篇关于单返回值的表值函数与标量值函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆