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

日時からのトリミング時間–フォローアップ

    日時からのトリミング時間に関する以前の投稿に続いて、データアクセスを伴わないさまざまなメソッドのパフォーマンス特性をより明確に示すことに拍車がかかりました。元の投稿では、日時の値を独立して日付に変換する7つの異なる方法をすばやく比較し、違いが無視できることを示した後、データを返す実際のクエリでのこれらの方法の使用の分析に直接移りました。

    この投稿では、実際のデータを導入せずに、日時から時間をトリミングするいくつかの異なる方法(実際には18の異なる方法!)を示し、このタスクを実行するための「最速」の方法を宣言できるかどうかを確認したいと思いました。

    メソッド

    これが私がテストする18の方法です。いくつかは私の前の投稿の後にMadhivananが指摘したブログ投稿から取られました:

    DECLARE @d DATETIME, @ds DATETIME = SYSDATETIME();

    テスト

    各変換を1,000,000回実行するループを作成し、18の変換方法すべてに対してこのプロセスを10回繰り返します。これにより、メソッドごとに10,000,000回のコンバージョンの指標が提供され、統計上の大きな偏りがなくなります。

    CREATE TABLE #s(j INT, ms INT);
    GO
    SET NOCOUNT ON;
    GO
    DECLARE @j INT = 1, @x INT, @i INT = 1000000;
    DECLARE @t DATETIME2, @d DATETIME, @ds DATETIME = SYSDATETIME();
     
    WHILE @j <= 18
    BEGIN
      SELECT @x = 1, @t = SYSDATETIME();
     
      WHILE @x <= @i
      BEGIN
        IF @j = 1
          SET @d = DATEDIFF(DAY, 0, @ds);
        IF @j = 2
          SET @d = CAST(@ds AS INT);
        IF @j = 3
          SET @d = CAST(CONVERT(CHAR(8), @ds, 112) AS DATETIME);
        IF @j = 4
          SET @d = DATEADD(DAY, DATEDIFF(DAY, 0, @ds), 0);
        IF @j = 5
          SET @d = CAST(CAST(SUBSTRING(CAST(@ds AS BINARY(8)), 1, 4) 
                   AS BINARY(8)) AS DATETIME);
        IF @j = 6
          SET @d = CONVERT(CHAR(8), @ds, 112);
        IF @J = 7
          SET @d = CAST(CAST(@ds AS VARCHAR(11)) AS DATETIME);
        IF @J = 8
          SET @d = @ds - CONVERT(CHAR(10), @ds, 108);
        IF @J = 9
          SET @d = @ds - CAST(CAST(@ds AS TIME) AS DATETIME);
        IF @J = 10
          SET @d = CAST(FLOOR(CAST(@ds AS FLOAT)) AS DATETIME);
        IF @J = 11
          SET @d = CAST(CAST(CAST(CAST(@ds AS BINARY(8)) AS BINARY(4)) 
                   AS BINARY(8)) AS DATETIME);
        IF @J = 12
          SET @d = @ds - CAST(@ds AS BINARY(4));
        IF @J = 13
          SET @d = DATEADD(DAY, CONVERT(INT, @ds - 0.5), 0);
        IF @J = 14
          SET @d = CONVERT(DATETIME, FORMAT(@ds, N'yyyy-MM-dd'));
        IF @J = 15
          SET @d = CONVERT(DATETIME,CONVERT(INT,CONVERT(FLOAT,@ds)));
        IF @J = 16
          SET @d = CAST(CAST(CAST(CAST(@ds AS BINARY(8)) AS BIGINT) & 
                   0XFFFFFFFF00000000 AS BINARY(8)) AS DATETIME);
        IF @J = 17
          SET @d = CONVERT(DATE, @ds);
        IF @j = 18
          SET @d = CAST(@ds AS DATE);
     
        SET @x += 1;
      END
     
      INSERT #s SELECT @j, DATEDIFF(MILLISECOND, @t, SYSDATETIME());
     
      SET @j += 1;
    END
    GO 10
     
    SELECT 
      j, method = CASE ... END, 
      MIN(ms), MAX(ms), AVG(ms)
    FROM #s
    GROUP BY j ORDER BY j;

    結果

    これは、SQL Server 2012(11.0.2376)を実行している8GBのRAMと4つのvCPUを備えたWindows8VMで実行しました。これが表形式の結果で、平均期間でソートされ、最初に最速です:

    そして、これが平均期間のグラフ表示です:

    <!-a target =_blank href ="http://www.sqldat.com/article/uploadfiles/202205/2022051415101018.png">

    外れ値(SQLServer2012の新しいFORMATを使用)を削除した場合 機能、この目的のための明らかな犬)、私たちはここで真の敗者を選ぶのに本当に苦労するでしょう。残りの17の方法のうち、この変換を100万回実行するために、最も遅い方法は、平均して最も速い方法よりもわずか3秒遅くなります。証拠は、CAST / CONVERTを使用するという私の以前の主張を依然として支持しています ネイティブでは、可能な限り効率的ですが、他のアプローチに対する改善はごくわずかであり、すべての実行で勝者でさえありませんでした。


    1. SQL Serverインスタンスでまだ使用されている廃止された機能を見つける最も簡単な方法(T-SQLの例)

    2. Oracle DROP TABLE IF EXISTS Alternatives

    3. Rails、PostgreSQL、および履歴トリガー

    4. Access2016でテーブルをバックエンドデータベースにリンクする方法