sql >> データベース >  >> RDS >> Sqlserver

テーブル値関数とスカラー値関数 単一の戻り値の関数

    ジョナサ・ディキンソンとの議論 (彼の回答を見てください) は、いくつかの簡単なテストを行うことになりました:

    純粋な埋め込みスカラー サブセレクト それほど悪くはありません。 ただ 1 つの値をクエリするだけでも最速 .予想通り、スカラー関数は悪いです。 TVF によって返されるフィールドが多いほど、相対的なパフォーマンスが向上します。

    唯一確実な答えは:スカラー関数が最悪 また、複数行の TVF は、ほとんどの場合、インラインよりも遅くなります。 アドホックなアプローチは高速になる傾向があります .

    しかし、すべての状況 (スカラー関数を除く) に特別なケースを設定することができ、1 つのアプローチが最速でした.

    結論:(いつものように :-) ) 場合によります...

    ヒント:多くのテーブルと列を持つ大規模なデータベースに対してこれを行うのが最善です.

    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. mysql-queryのwhere句が多すぎますか?

    2. MySQL-結合付きのGROUP_CONCAT

    3. ずっと前に尋ねられたクエリのIDを取得して、別のテーブルに投稿するにはどうすればよいですか?

    4. スカラー集計を使用したインデックス付きビューのバグ