• SQL Server ->> Computed Column(计算列)


    Computed Column(计算列)是自SQL Server 2005开始就有的特性。计算列的定义是一个表达式。表达式可以是非计算列,常量,函数间的组合。但是不可以是子查询。

    计算列数据固化

    默认情况下计算列的数据是存储在磁盘上,仅当计算列被查询引用是才进行实时计算。只在计算列在定义是添加了PERSISTED关键词是才将数据固化。

    计算列上创建索引或者作为分区函数的引用列

    计算列上是运行创建索引和作为分区函数的引用列。但是必须指定PERSISTED关键词。

    用法其实很简单。那么这里有些问题。使用计算列的代价到底有多大?

    INSERT发生时使用计算列和非计算列的性能区别

    这里做一个测试。首先创建好两张表

    IF EXISTS(SELECT * FROM sys.tables WHERE name = 'computed_column_test_computed')
    BEGIN
        DROP TABLE dbo.computed_column_test_computed
    END
    
    IF EXISTS(SELECT * FROM sys.tables WHERE name = 'computed_column_test_noncomputed')
    BEGIN
        DROP TABLE dbo.computed_column_test_noncomputed
    END
    
    CREATE TABLE dbo.computed_column_test_computed
    (
        dttm DATETIME,
        dttm_year AS YEAR(dttm) PERSISTED,
        dttm_month AS MONTH(dttm) PERSISTED,
        dttm_nextday AS DATEADD(DAY,1,dttm) PERSISTED,
        dttm_previousday AS DATEADD(DAY,-1,dttm) PERSISTED,
        dttm_week AS DATEPART(ww,dttm),
        dttm_monthname AS CASE DATEPART(mm, dttm)
                            WHEN 1 THEN 'January'
                            WHEN 2 THEN 'February'
                            WHEN 3 THEN 'March'
                            WHEN 4 THEN 'April'
                            WHEN 5 THEN 'May'
                            WHEN 6 THEN 'June'
                            WHEN 7 THEN 'July'
                            WHEN 8 THEN 'August'
                            WHEN 9 THEN 'September'
                            WHEN 10 THEN 'October'
                            WHEN 11 THEN 'November'
                            WHEN 12 THEN 'December'
                          END PERSISTED,
        dttm_quarter AS DATEPART(qq,dttm) PERSISTED
    )
    
    
    CREATE TABLE dbo.computed_column_test_noncomputed
    (
        dttm DATETIME,
        dttm_year SMALLINT,
        dttm_month SMALLINT,
        dttm_nextday DATETIME,
        dttm_previousday DATETIME,
        dttm_week INT,
        dttm_monthname VARCHAR(30),
        dttm_quarter VARCHAR(30)
    )

    然后开启IO和TIME的统计信息开关,然后分别对两张表进行数据插入。

    SET STATISTICS TIME ON
    SET STATISTICS IO ON
    
    INSERT dbo.computed_column_test_computed(
    dttm
    )
    SELECT DATEADD(SECOND, Num, GETDATE())
    FROM dbo.Numbers
    WHERE Num <= 1000000
    
    INSERT dbo.computed_column_test_noncomputed(dttm ,
        dttm_year ,
        dttm_month ,
        dttm_nextday ,
        dttm_previousday ,
        dttm_week ,
        dttm_monthname ,
        dttm_quarter)
    SELECT     GETDATE(),
            YEAR(GETDATE()) PERSISTED,
            MONTH(GETDATE()) PERSISTED,
            DATEADD(DAY,1,GETDATE()) ,
            DATEADD(DAY,-1,GETDATE()),
            DATEPART(ww,GETDATE()),
            CASE DATEPART(mm, GETDATE())
            WHEN 1 THEN 'January'
            WHEN 2 THEN 'February'
            WHEN 3 THEN 'March'
            WHEN 4 THEN 'April'
            WHEN 5 THEN 'May'
            WHEN 6 THEN 'June'
            WHEN 7 THEN 'July'
            WHEN 8 THEN 'August'
            WHEN 9 THEN 'September'
            WHEN 10 THEN 'October'
            WHEN 11 THEN 'November'
            WHEN 12 THEN 'December'
            END,
        DATEPART(qq,GETDATE())
    FROM dbo.Numbers
    WHERE Num <= 1000000

    我的例子里面分别进行10万行、30万行、50万行和100万行数据的插入测试。一共有7个计算列。每个例子测试两次。

     SQL Server Execution Times:
       CPU time = 0 ms,  elapsed time = 0 ms.
    Table 'computed_column_test_computed'. Scan count 0, logical reads 100840, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    Table 'Numbers'. Scan count 1, logical reads 164, physical reads 2, read-ahead reads 162, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    
     SQL Server Execution Times:
       CPU time = 515 ms,  elapsed time = 1564 ms.
    
    (100000 row(s) affected)
    
    
    
    
    SQL Server parse and compile time: 
       CPU time = 0 ms, elapsed time = 1327 ms.
    Table 'computed_column_test_noncomputed'. Scan count 0, logical reads 100833, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    Table 'Numbers'. Scan count 1, logical reads 164, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    
     SQL Server Execution Times:
       CPU time = 265 ms,  elapsed time = 759 ms.
    
    (100000 row(s) affected)
    
    
    
    
    
    
    SQL Server parse and compile time: 
       CPU time = 0 ms, elapsed time = 5 ms.
    
     SQL Server Execution Times:
       CPU time = 0 ms,  elapsed time = 0 ms.
    
     SQL Server Execution Times:
       CPU time = 0 ms,  elapsed time = 0 ms.
    Table 'computed_column_test_computed'. Scan count 0, logical reads 100840, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    Table 'Numbers'. Scan count 1, logical reads 164, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    
     SQL Server Execution Times:
       CPU time = 391 ms,  elapsed time = 411 ms.
    
    (100000 row(s) affected)
    Table 'computed_column_test_noncomputed'. Scan count 0, logical reads 100833, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    Table 'Numbers'. Scan count 1, logical reads 164, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    
     SQL Server Execution Times:
       CPU time = 234 ms,  elapsed time = 273 ms.
    
    (100000 row(s) affected)
    
    
    
    
    
    
    
    
     SQL Server Execution Times:
       CPU time = 0 ms,  elapsed time = 0 ms.
    SQL Server parse and compile time: 
       CPU time = 0 ms, elapsed time = 6 ms.
    Table 'computed_column_test_computed'. Scan count 0, logical reads 302521, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    Table 'Numbers'. Scan count 1, logical reads 487, physical reads 1, read-ahead reads 330, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    
     SQL Server Execution Times:
       CPU time = 1250 ms,  elapsed time = 1986 ms.
    
    (300000 row(s) affected)
    SQL Server parse and compile time: 
       CPU time = 0 ms, elapsed time = 74 ms.
    Table 'computed_column_test_noncomputed'. Scan count 0, logical reads 302499, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    Table 'Numbers'. Scan count 1, logical reads 487, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    
     SQL Server Execution Times:
       CPU time = 813 ms,  elapsed time = 966 ms.
    
    (300000 row(s) affected)
    
    
    
    
    SQL Server parse and compile time: 
       CPU time = 0 ms, elapsed time = 14 ms.
    Table 'computed_column_test_computed'. Scan count 0, logical reads 302521, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    Table 'Numbers'. Scan count 1, logical reads 487, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    
     SQL Server Execution Times:
       CPU time = 1156 ms,  elapsed time = 1709 ms.
    
    (300000 row(s) affected)
    Table 'computed_column_test_noncomputed'. Scan count 0, logical reads 302499, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    Table 'Numbers'. Scan count 1, logical reads 487, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    
     SQL Server Execution Times:
       CPU time = 734 ms,  elapsed time = 3089 ms.
    
    (300000 row(s) affected)
    
    
    
    
    
    
    SQL Server parse and compile time: 
       CPU time = 8 ms, elapsed time = 8 ms.
    Table 'computed_column_test_computed'. Scan count 0, logical reads 504201, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    Table 'Numbers'. Scan count 1, logical reads 809, physical reads 0, read-ahead reads 315, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    
     SQL Server Execution Times:
       CPU time = 2031 ms,  elapsed time = 2080 ms.
    
    (500000 row(s) affected)
    Table 'computed_column_test_noncomputed'. Scan count 0, logical reads 504166, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    Table 'Numbers'. Scan count 1, logical reads 809, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    
     SQL Server Execution Times:
       CPU time = 1297 ms,  elapsed time = 2915 ms.
    
    (500000 row(s) affected)
    
    
    
    
    
    SQL Server parse and compile time: 
       CPU time = 0 ms, elapsed time = 0 ms.
    SQL Server parse and compile time: 
       CPU time = 0 ms, elapsed time = 4 ms.
    Table 'computed_column_test_computed'. Scan count 0, logical reads 504201, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    Table 'Numbers'. Scan count 1, logical reads 809, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    
     SQL Server Execution Times:
       CPU time = 1984 ms,  elapsed time = 3540 ms.
    
    (500000 row(s) affected)
    SQL Server parse and compile time: 
       CPU time = 0 ms, elapsed time = 2 ms.
    Table 'computed_column_test_noncomputed'. Scan count 0, logical reads 504166, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    Table 'Numbers'. Scan count 1, logical reads 809, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    
     SQL Server Execution Times:
       CPU time = 1266 ms,  elapsed time = 1341 ms.
    
    (500000 row(s) affected)
    
    
    
    
    
    
    SQL Server parse and compile time: 
       CPU time = 13 ms, elapsed time = 13 ms.
    Table 'computed_column_test_computed'. Scan count 0, logical reads 1008359, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    Table 'Numbers'. Scan count 1, logical reads 1615, physical reads 0, read-ahead reads 791, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    
     SQL Server Execution Times:
       CPU time = 4500 ms,  elapsed time = 9110 ms.
    
    (1000000 row(s) affected)
    Table 'computed_column_test_noncomputed'. Scan count 0, logical reads 1008333, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    Table 'Numbers'. Scan count 1, logical reads 1615, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    
     SQL Server Execution Times:
       CPU time = 2531 ms,  elapsed time = 3903 ms.
    
    (1000000 row(s) affected)
    
    
    
    
    
    
    SQL Server parse and compile time: 
       CPU time = 0 ms, elapsed time = 0 ms.
    SQL Server parse and compile time: 
       CPU time = 0 ms, elapsed time = 3 ms.
    Table 'computed_column_test_computed'. Scan count 0, logical reads 1008359, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    Table 'Numbers'. Scan count 1, logical reads 1615, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    
     SQL Server Execution Times:
       CPU time = 3797 ms,  elapsed time = 6559 ms.
    
    (1000000 row(s) affected)
    SQL Server parse and compile time: 
       CPU time = 0 ms, elapsed time = 3 ms.
    Table 'computed_column_test_noncomputed'. Scan count 0, logical reads 1008333, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    Table 'Numbers'. Scan count 1, logical reads 1615, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    
     SQL Server Execution Times:
       CPU time = 2422 ms,  elapsed time = 3895 ms.
    
    (1000000 row(s) affected)

    可以看到确实使用computed column会对性能有一定的影响。当计算列数量越多的情况下性能的影响越大。但是当计算列数量很少的情况下,影响或者说差别其实很小很小。以我做的实验为例,讲计算列数量减少到只有3个,数据量依旧停留在100万行的情况,两者的性能差异其实已经很小了。

    SQL Server parse and compile time: 
       CPU time = 0 ms, elapsed time = 4 ms.
    
     SQL Server Execution Times:
       CPU time = 0 ms,  elapsed time = 0 ms.
    
     SQL Server Execution Times:
       CPU time = 0 ms,  elapsed time = 0 ms.
    Table 'computed_column_test_computed'. Scan count 0, logical reads 1005813, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    Table 'Numbers'. Scan count 1, logical reads 1615, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    
     SQL Server Execution Times:
       CPU time = 3203 ms,  elapsed time = 5058 ms.
    
    (1000000 row(s) affected)
    Table 'computed_column_test_noncomputed'. Scan count 0, logical reads 1005319, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    Table 'Numbers'. Scan count 1, logical reads 1615, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    
     SQL Server Execution Times:
       CPU time = 2281 ms,  elapsed time = 4747 ms.
    
    (1000000 row(s) affected)
    
    
    
    
    SQL Server parse and compile time: 
       CPU time = 16 ms, elapsed time = 28 ms.
    Table 'computed_column_test_computed'. Scan count 0, logical reads 1005813, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    Table 'Numbers'. Scan count 1, logical reads 1615, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    
     SQL Server Execution Times:
       CPU time = 2984 ms,  elapsed time = 3512 ms.
    
    (1000000 row(s) affected)
    Table 'computed_column_test_noncomputed'. Scan count 0, logical reads 1005319, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    Table 'Numbers'. Scan count 1, logical reads 1615, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    
     SQL Server Execution Times:
       CPU time = 2672 ms,  elapsed time = 2859 ms.
    
    (1000000 row(s) affected)

    那么总结下,计算列的使用原则我认为是在表中计算列的数量本身不多,而且一次性数据行插入量不大,计算逻辑固定,计算复杂度大的情况下,推荐使用计算列。

    比如像DimDate这种表,表中可能有非常多的属性列用于表示当前日期的一些额外属性,比如下一天的日期,前一天的日期等等。用计算列是一个很好的选择。

    参考:

    Computed Columns

  • 相关阅读:
    margin和pading的百分比值
    Vue中的computed和watch
    JS的自身属性和继承属性
    JS对象的可枚举属性和不可枚举属性
    Dart语言学习
    Practice_Test
    Lesson2 basic python_20200920
    Python 基础语法L1
    小男孩和狗的故事
    智者的故事
  • 原文地址:https://www.cnblogs.com/jenrrychen/p/5419035.html
Copyright © 2020-2023  润新知