Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Функция с таблични стойности срещу функция за скаларни стойности за единична върната стойност

Дискусията ми с Джоната Дикинсън (вижте неговия отговор) ме накара да направя няколко бързи теста:

Оказва се, че чистият, вграден скаларен подизбор не е толкова лошо. Запитването на само една стойност е дори най-бързо . Както се очаква, скаларната функция е лоша. Колкото повече полета се връщат от TVF, толкова по-добро е относителното увеличение на производителността.

Единственият сигурен отговор е:Скаларната функция е най-лошата и многоредовият TVF е - през повечето време - по-бавен от вградения. Всеки ad hoc подход обикновено е по-бърз .

Но можех да настроя специални случаи за всички ситуации (с изключение на скаларната функция), където един подход беше най-бързият.

Заключение:(както винаги :-) ) Зависи...

Подсказка:Най-добре е да оставите това срещу голяма база данни с много таблици и колони.

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;


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Какво НЕ е логически оператор в SQL Server - SQL Server / TSQL урок, част 121

  2. пребройте броя на колоните, които имат данни за всеки ред

  3. Как да подобрим производителността за филтриране по дата и час в SQL Server?

  4. Как мога да направя нещо като:ИЗПОЛЗВАЙТЕ @databaseName

  5. MSSQL в python 2.7