• 【译】SQLskills SQL101:Trace Flags、ERRORLOG、Update Statistics


    最近阅读SQLskills SQL101,将Erin Stellato部分稍作整理。仅提取自己感兴趣的知识点,详细内容请阅读原文。


    一、Trace Flags
    推荐开启三个跟踪标记1118、3023、3226
    跟踪标记1118(适用2016之前版本),避开对SGAM页的使用,在统一区分配新建对象的空间。
    跟踪标记3023(适用2014之前版本),在默认情况下对实例上进行的所有备份启用CHECKSUM选项。
    跟踪标记3226,成功备份信息不再写入SQL Server ERRORLOG

    启动参数添加:-T3226
    DBCC TRACEON(3226,-1) --第二个参数-1表示实例级别,否则会话级别
    View Code

    二、The SQL Server ERRORLOG
    1、设定作业定期recycle错误日志(weekly)
    EXEC master..sp_cycle_errorlog
    EXEC msdb..sp_cycle_agent_errorlog
    2、配置SQL Server 错误日志文件在回收之前的数目(30)
    SSMS->实例->管理->SQL Server 日志->配置
    三、Updating SQL Server Statistics Part I – Automatic Updates
    为了自动更新统计信息,必须为数据库启用[自动更新统计信息]数据库选项
    可以使用以下语句检查[自动更新统计信息]选项是否启用

    SELECT
        [name] [DatabaseName],
        CASE
            WHEN [is_auto_update_stats_on] = 1 THEN 'Enabled'
            ELSE 'Disabled'
        END [AutoUpdateStats]
    FROM [sys].[databases]
    ORDER BY [name];
    GO
    View Code

    使用以下语句启用[自动更新统计信息]选项

    USE [master]
    GO
    ALTER DATABASE [<database_name>] SET AUTO_UPDATE_STATISTICS ON WITH NO_WAIT
    GO
    View Code

    启用选项后,SQL Server根据内部阈值将统计信息标记为过期:
    对于SQL Server 2014及之前版本,阈值是500+(20%×表格数据总量)。当然也有例外(数据量小于500行的表格,表变量上不能建统计信息)
    对于SQL Server 2008 R2 SP1及之后版本,可以使用跟踪标记2371降低这个阈值
    对于SQL Server 2016,如果数据库的兼容级别为130,默认使用跟踪标志2371引入的阈值;如果数据库的兼容级别<=120,则需使用跟踪标记2371来降低阈值
    如果统计信息被标记为过时,那么在下一次使用的时候,SQL Server将自动更新它们。注意,它们并不是在过期的时刻就更新,它们在需要的时候才会更新。
    四、Updating SQL Server Statistics Part II – Scheduled Updates
    4.1、Update Statistics Task
    维护计划中的"更新统计信息"任务,你可以配置所有数据库或者特定数据库,你还可以确定更新选项(所有、列统计、索引统计),扫描类型(完全、按行数抽样、按百分比抽样)

    /* Update Statistics Task 对应的脚本(截取部分) */
    --所有现有统计信息,完全扫描
    USE [AdventureWorks2008R2]
    GO
    UPDATE STATISTICS [dbo].[ErrorLog] 
    WITH FULLSCAN
    GO
    --仅限列统计信息,按行数抽样
    USE [AdventureWorks2008R2]
    GO
    UPDATE STATISTICS [dbo].[ErrorLog] 
    WITH SAMPLE 50 ROWS,COLUMNS
    GO
    --仅限索引统计信息,按百分比抽样
    USE [AdventureWorks2008R2]
    GO
    UPDATE STATISTICS [dbo].[ErrorLog] 
    WITH SAMPLE 50 PERCENT,INDEX
    GO
    View Code

    经常有人在Rebuild Index Task之后添加Update Statistics Task。如果是在SQL Server 2014及之前的版本,你只需要更新列统计信息即可,因为Rebuild Index Task会Rebuild所有的索引,并且使用完全扫描更新统计信息。在SQL Server 2016,Rebuild Index Task提供更多选项,你可以配置当索引碎片达到指定数值时才Rebuild索引。这样部分索引Rebuild(统计信息更新),部分索引未Rebuild(统计信息没更新)。Update Statistics Task应该如何配置?这种情况你可能选择更新所有现有统计信息,部分统计信息会再次更新——真是浪费!
    4.2、sp_updatestats
    sp_updatestats命令用于数据库级别,它不能指定统计或者索引或者表。只要数据发生变化,sp_updatestats命令就会更新统计信息

    /* sp_updatestats 测试 */
    USE AdventureWorks2008R2
    GO
    --执行命令
    exec sp_updatestats
    ......
    正在更新 [Sales].[SalesOrderDetail]
        [PK_SalesOrderDetail_SalesOrderID_SalesOrderDetailID],不需要更新...
        [AK_SalesOrderDetail_rowguid],不需要更新...
        [IX_SalesOrderDetail_ProductID],不需要更新...
        [_WA_Sys_00000006_3587F3E0],不需要更新...
        [_WA_Sys_00000002_3587F3E0],不需要更新...
        [_WA_Sys_00000004_3587F3E0],不需要更新...
        [_WA_Sys_00000007_3587F3E0],不需要更新...
        [_WA_Sys_0000000B_3587F3E0],不需要更新...
        已更新 0 条索引/统计信息,8 不需要更新。
    ......
    --查看统计更新时间
    DBCC SHOW_STATISTICS ('Sales.SalesOrderDetail',IX_SalesOrderDetail_ProductID)
    Name    Updated
    IX_SalesOrderDetail_ProductID    08 16 2017  4:30PM
    
    --更新一行数据
    UPDATE Sales.SalesOrderDetail
    SET ProductID = ProductID
    WHERE SalesOrderDetailID=1
    
    --执行命令
    exec sp_updatestats
    ......
    正在更新 [Sales].[SalesOrderDetail]
        [PK_SalesOrderDetail_SalesOrderID_SalesOrderDetailID],不需要更新...
        [AK_SalesOrderDetail_rowguid],不需要更新...
        [IX_SalesOrderDetail_ProductID] 已更新...
        [_WA_Sys_00000006_3587F3E0],不需要更新...
        [_WA_Sys_00000002_3587F3E0],不需要更新...
        [_WA_Sys_00000004_3587F3E0],不需要更新...
        [_WA_Sys_00000007_3587F3E0],不需要更新...
        [_WA_Sys_0000000B_3587F3E0],不需要更新...
        已更新 1 条索引/统计信息,7 不需要更新。
    ......
    --查看统计更新时间
    DBCC SHOW_STATISTICS ('Sales.SalesOrderDetail',IX_SalesOrderDetail_ProductID)
    Name    Updated
    IX_SalesOrderDetail_ProductID    08 16 2017  4:32PM
    View Code

    可以看到哪怕只是更新一行,统计信息也会更新!显然这种更新统计没太大意义。
    4.3、UPDATE STATISTICS
    UPDATE STATISTICS命令可以针对单个统计信息或者单个表(更新表上的所有统计信息)。推荐使用此命令编写更新统计信息语句,我喜欢根据已经更改的数据量更新过时的统计信息。
    我们通过使用sys.dm_db_stats_properties来确定是否更新统计信息。这个动态管理函数跟踪修改,并且告诉我们在上一次更新统计信息时表中有多少行,以及统计更新的时间,以及上一次更新统计信息后累计变更的行数。例如,我更新Sales.SalesOrderDetail表中的部分行,然后查看此DMF输出,你可以看到modification_counter和我修改的行数一致

    /* UPDATE STATISTICS 测试 */
    USE [AdventureWorks2008R2];
    GO
    --更新部分行,9831行受影响
    UPDATE [Sales].[SalesOrderDetail]
    SET [ProductID] = [ProductID]
    WHERE [ProductID] IN (921,873,712);
    GO
    --从sys.dm_db_stats_properties中查看上次统计更新信息
    SELECT [so].[name] [TableName],
           [ss].[name] [StatisticName],
           [ss].[stats_id] [StatisticID],
           [sp].[last_updated] [LastUpdated],
           [sp].[rows] [RowsInTableWhenUpdated],
           [sp].[rows_sampled] [RowsSampled],
           [sp].[modification_counter] [NumberOfModifications]
    FROM   [sys].[stats] [ss]
           JOIN [sys].[objects] [so]
                ON  [ss].[object_id] = [so].[object_id]
           CROSS APPLY [sys].[dm_db_stats_properties] ([so].[object_id], [ss].stats_id) [sp]
    WHERE  [so].[name] = N'SalesOrderDetail';
    GO
    View Code


    连续执行三次更新,受影响行数累计达到9831*3=29493>24763=121317*20%+500,[自动更新统计信息]选项为True,下一次使用索引时就会触发更新统计信息。
    有了上面的数据后,我们可以根据已修改行数所占比例决定是否更新统计信息。很有可能一些统计信息需要每天更新,因为数据变化很大,而其他统计信息只需要每周更新一次或每月更新一次,因为数据变化不大。
    无论你使用哪种方式手动更新统计信息,确保通过代理作业定期执行,同时确保已启用[自动更新统计信息]选项。谁也不能保证作业始终正常执行,同时也无法保证作业异常时能及时通知你。

  • 相关阅读:
    Spring--AOP--面向切面编程
    Spring ---annotation (重点)--Resource, Component 重要!!!
    Spring ---annotation (重点)--AutoWired 不常用
    ts 交集类型
    ts 使用 keyof typeof
    Dart 编写Api弃用警告
    js 反应&行动
    perl 打印简单的help文档
    perl 在windows上获取当前桌面壁纸
    perl 打印目录结构
  • 原文地址:https://www.cnblogs.com/Uest/p/7205560.html
Copyright © 2020-2023  润新知