Moja rozmowa z Jonathą Dickinsonem (spójrz na jego odpowiedź) skłoniła mnie do przeprowadzenia kilku szybkich testów:
Okazuje się, że czysty, osadzony podwybór skalarny nie jest tak źle. Zapytanie tylko jedna wartość jest nawet najszybsze . Zgodnie z oczekiwaniami funkcja skalarna jest zła. Im więcej pól jest zwracanych przez TVF, tym lepszy jest względny wzrost wydajności.
Jedyną pewną odpowiedzią jest:Funkcja skalarna jest najgorsza a wieloliniowy TVF jest - przez większość czasu - wolniejszy niż inline. Każde podejście ad hoc jest zwykle szybsze .
Ale mogłem ustawić specjalne przypadki we wszystkich sytuacjach (z wyjątkiem funkcji skalarnej), w których jedno podejście było najszybsze.
Wniosek:(jak zawsze :-) ) To zależy...
Wskazówka:najlepiej jest pozwolić, aby to działało w dużej bazie danych z wieloma tabelami i kolumnami.
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 [email protected] AND [email protected]);
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 [email protected] AND [email protected]);
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 [email protected] AND [email protected] GROUP BY c.TABLE_SCHEMA,c.TABLE_NAME) AS ColCounter
,(SELECT COUNT(*) FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS c WHERE [email protected] AND [email protected] 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 [email protected] AND [email protected] GROUP BY c.TABLE_SCHEMA,c.TABLE_NAME) AS ColCounter
,(SELECT COUNT(*) FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS c WHERE [email protected] AND [email protected] 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()[email protected] 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()[email protected] 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()[email protected] 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()[email protected] 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()[email protected] 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;