前几天,在所有数据库服务器部署了监控磁盘空间的存储过程和作业后(MS SQL 监控磁盘空间告警),今天突然收到了两封告警邮件,好吧,存储规划是一方面,但是,是不是要分析一下是什么原因造成磁盘空间不足的呢?会不会是因为突然暴增的日志文件,抑或是系统业务猛增导致数据量暴增,还是历史数据累计原因....分析总得有数据来支撑吧,但是现在只有那些数据文件的当前大小信息,没有数据文件的历史增长变化信息,所以,今天就想实现这么一个功能,每天(频率可以调整)去收集一下数据文件的信息,放到一个表里面,这样方便我们分析数据文件的增长演变例程,甚至你可以将数据文件的增长幅度和业务变化关联起来分析....
 
那么接下来就是我的设计思路和实现代码,目前只是简单实现,以后将继续优化,丰富一些功能。
首先我们创建一个表DiskCapacityHistory,用来保存数据库文件的历史增长变化信息:
USE  msdb;
GOIF  EXISTS (SELECT 1 FROM dbo.sysobjects WHERE id = OBJECT_ID(N'') AND xtype='U')DROP TABLE DiskCapacityHistory;
GOCREATE TABLE dbo.DiskCapacityHistory
([Date_CD]            INT                     ,[DataBaseID]         INT                     ,[FileID]             INT                     ,[DataBaseName]       sysname                 ,[LogicalName]        VARCHAR(32)             ,[FileTypeDesc]       NVARCHAR(60)            ,[PhysicalName]       NVARCHAR(260)          ,[StateDesc]          NVARCHAR(60)           ,[MaxSize]            NVARCHAR(32)            ,[GrowthType]         NVARCHAR(8)             ,[IsReadOnly]         INT                     ,[IsPercentGrowth]    SMALLINT                ,[Size]               FLOAT                   ,[Growth_MOM_RAT]     FLOAT                   ,[Growth_YOY_RAT]     FLOAT                   ,CONSTRAINT PK_DiskCapacityHistory PRIMARY KEY(Date_CD, DataBaseID, FileID)
);

View Code

EXEC sys.sp_addextendedproperty @name = N'MS_Description', @value = '日期编码', @level0type = N'SCHEMA', @level0name = N'dbo', @level1type = N'TABLE', @level1name = N'DiskCapacityHistory', @level2type = N'COLUMN', @level2name = N'Date_CD';EXEC sys.sp_addextendedproperty @name = N'MS_Description', @value = '数据库标识', @level0type = N'SCHEMA', @level0name = N'dbo', @level1type = N'TABLE', @level1name = N'DiskCapacityHistory', @level2type = N'COLUMN', @level2name = N'DataBaseID';EXEC sys.sp_addextendedproperty @name = N'MS_Description', @value = '文件标识', @level0type = N'SCHEMA', @level0name = N'dbo', @level1type = N'TABLE', @level1name = N'DiskCapacityHistory', @level2type = N'COLUMN', @level2name = N'FileID';EXEC sys.sp_addextendedproperty @name = N'MS_Description', @value = '数据库名称', @level0type = N'SCHEMA', @level0name = N'dbo', @level1type = N'TABLE', @level1name = N'DiskCapacityHistory', @level2type = N'COLUMN', @level2name = N'DataBaseName';EXEC sys.sp_addextendedproperty @name = N'MS_Description', @value = '数据库逻辑名称', @level0type = N'SCHEMA', @level0name = N'dbo', @level1type = N'TABLE', @level1name = N'DiskCapacityHistory', @level2type = N'COLUMN', @level2name = N'LogicalName';EXEC sys.sp_addextendedproperty @name = N'MS_Description', @value = '文件类型描述', @level0type = N'SCHEMA', @level0name = N'dbo', @level1type = N'TABLE', @level1name = N'DiskCapacityHistory', @level2type = N'COLUMN', @level2name = N'FileTypeDesc';EXEC sys.sp_addextendedproperty @name = N'MS_Description', @value = '物理数据库文件', @level0type = N'SCHEMA', @level0name = N'dbo', @level1type = N'TABLE', @level1name = N'DiskCapacityHistory', @level2type = N'COLUMN', @level2name = N'PhysicalName';EXEC sys.sp_addextendedproperty @name = N'MS_Description', @value = '文件最大大小', @level0type = N'SCHEMA', @level0name = N'dbo', @level1type = N'TABLE', @level1name = N'DiskCapacityHistory', @level2type = N'COLUMN', @level2name = N'MaxSize';EXEC sys.sp_addextendedproperty @name = N'MS_Description', @value = '文件增长类型', @level0type = N'SCHEMA', @level0name = N'dbo', @level1type = N'TABLE', @level1name = N'DiskCapacityHistory', @level2type = N'COLUMN', @level2name = N'GrowthType';EXEC sys.sp_addextendedproperty @name = N'MS_Description', @value = '是否只读类型', @level0type = N'SCHEMA', @level0name = N'dbo', @level1type = N'TABLE', @level1name = N'DiskCapacityHistory', @level2type = N'COLUMN', @level2name = N'IsReadOnly';EXEC sys.sp_addextendedproperty @name = N'MS_Description', @value = '是否按百分比增长', @level0type = N'SCHEMA', @level0name = N'dbo', @level1type = N'TABLE', @level1name = N'DiskCapacityHistory', @level2type = N'COLUMN', @level2name = N'IsPercentGrowth';EXEC sys.sp_addextendedproperty @name = N'MS_Description', @value = '数据文件大小(GB)', @level0type = N'SCHEMA', @level0name = N'dbo', @level1type = N'TABLE', @level1name = N'DiskCapacityHistory', @level2type = N'COLUMN', @level2name = N'Size';EXEC sys.sp_addextendedproperty @name = N'MS_Description', @value = '文件增长环比(%)', @level0type = N'SCHEMA', @level0name = N'dbo', @level1type = N'TABLE', @level1name = N'DiskCapacityHistory', @level2type = N'COLUMN', @level2name = N'Growth_MOM_RAT';EXEC sys.sp_addextendedproperty @name = N'MS_Description', @value = '文件增长同比(%)', @level0type = N'SCHEMA', @level0name = N'dbo', @level1type = N'TABLE', @level1name = N'DiskCapacityHistory', @level2type = N'COLUMN', @level2name = N'Growth_YOY_RAT';GOIF  OBJECT_ID(N'sp_diskcapacity_cal')  IS NOT NULLDROP PROCEDURE sp_diskcapacity_cal;
GO

接下来,我们创建存储过程,负责来收集、统计这些数据库的文件的相关信息。关于环比/同比,正常情况一般是:

环比:  (指标当前值 - 指标值(上个月同一天))/ 指标值(上个月同一天) 。

同比:  (指标当前值 - 指标值(去年月同一天))/ 指标值(去年月同一天) 。

其实如果关注每天的数据文件变化情况,这个代码里面的环比、同比其实意义不大,其实我们可以这样定义环比、同比:

环比: (指标当前值 - 指标值(昨天))/指标值(昨天)。

同比: (指标当前值 - 指标值 (上个月))/指标值(上个月)

当然,你也可以把这四个指标都加上,对比参考,侧重点不同而已。

存储过程
  1. IF  OBJECT_ID(N'sp_diskcapacity_cal')IS NOT NULL
  2. DROP PROCEDURE sp_diskcapacity_cal;
  3. GO
  4. CREATE PROCEDURE dbo.sp_diskcapacity_cal
  5. AS
  6. BEGIN
  7. INSERT INTO dbo.DiskCapacityHistory
  8. (
  9. [Date_CD]           ,
  10. [DataBaseID]        ,
  11. [FileID]            ,
  12. [DataBaseName]      ,
  13. [LogicalName]       ,
  14. [FileTypeDesc]      ,
  15. [PhysicalName]      ,
  16. [StateDesc]         ,
  17. [MaxSize]           ,
  18. [GrowthType]        ,
  19. [IsReadOnly]        ,
  20. [IsPercentGrowth]   ,
  21. [Size]
  22. )
  23. SELECT CAST(REPLACE(CONVERT(varchar(10),GETDATE(),120),'-','') AS INT)
  24. AS DateCD        ,
  25. database_id                                                     AS DataBaseId    ,
  26. file_id                                                         AS FileID        ,
  27. DB_NAME(database_id)                                            AS DataBaseName  ,
  28. name                                                            AS LogicalName   ,
  29. type_desc                                                       AS FileTypeDesc  ,
  30. physical_name                                                   AS PhysicalName  ,
  31. state_desc                                                      AS StateDesc     ,
  32. CASE WHEN max_size = 0 THEN N'不允许增长'
  33. WHEN max_size = -1 THEN N'自动增长'
  34. ELSE LTRIM(STR(max_size * 8.0 / 1024 / 1024, 14, 2)) + 'G'
  35. END                                                             AS MaxSize       ,
  36. CASE WHEN is_percent_growth = 1
  37. THEN RTRIM(CAST(Growth AS CHAR(10))) + '%'
  38. ELSE RTRIM(CAST(Growth AS CHAR(10))) + 'M'
  39. END                                                             AS Growth        ,
  40. Is_Read_Only AS IsReadOnly ,
  41. Is_Percent_Growth AS IsPercentGrowth ,
  42. CAST(size * 8.0 / 1024 / 1024 AS DECIMAL(8, 4))                 AS Size
  43. FROM   sys.master_files;
  44. MERGE INTO dbo.DiskCapacityHistory DM USING
  45. (
  46. SELECT M.Date_CD        ,
  47. M.DataBaseID     ,
  48. M.FileID         ,
  49. CASE WHEN N.SIZE IS NULL OR N.SIZE = 0 THEN 0 ELSE
  50. (M.SIZE - N.SIZE)/N.SIZE END AS Growth_MOM_RAT
  51. FROM dbo.DiskCapacityHistory M
  52. LEFT JOIN dbo.DiskCapacityHistory  N ON
  53. CAST(CAST(M.Date_CD AS CHAR(8)) AS DATE) = DATEADD(MONTH, 1, CAST(CAST(N.Date_CD AS CHAR(8)) AS DATE))
  54. AND M.DataBaseID = N.DataBaseID AND M.FileID = N.FileID
  55. WHERE M.Date_CD =  CAST(REPLACE(CONVERT(varchar(10),GETDATE(),120),'-','') AS INT)
  56. ) TMP
  57. ON
  58. (
  59. DM.Date_CD       = TMP.Date_CD     AND
  60. DM.DatabaseId    = TMP.DataBaseId  AND
  61. DM.FileId        = TMP.FileId
  62. )
  63. WHEN MATCHED THEN UPDATE SET
  64. DM.Growth_MOM_RAT = TMP.Growth_MOM_RAT;
  65. END
  66. GO

顺便吐槽一下:由于前两年一直使用ORACLE数据库,很少接触SQL SERVER,在实现上面功能的时候,我深深的体会到了ORACLE和SQL SERVER的巨大差距,如果用PL/SQL实现,那非常方便快捷,但是用T-SQL让我遇到了几个相当痛苦地方,下面顺便记录对比一下吧:

 
一:由于我采用INT来保存日期数据,那么需要在DATE类型和INT类型之间转换,我们来对比一下两者的差别吧:
 
 
1.1 DATE类型转换为整型:
 
T-SQL:
SELECT CAST(REPLACE(CONVERT(varchar(10),GETDATE(),120),'-','') AS INT);

PL/SQL:
 
SELECT TO_CHAR(Date_CD, 'YYYYMMDD') FROM DUAL;

 
1.2 整型转换为DATE类型(字段DATE_CD)
 
T-SQL:
   
    SELECT CAST(CAST(DATE_CD AS CHAR(8)) AS DATE) FROM TEST;
 
PL/SQL:
 
    SELECT TO_DATE(DATE_CD, 'YYYY-MM-DD') FROM TEST;
 
结论: 纯属个人感受,从上面的脚本的简单性,方便性上,感觉ORACLE完胜SQL SERVER
二:计算数据文件增长同比、环比值
 
  1:SQL SERVER 2005 没有MERGE语句功能,上面的脚本得改写成
Code Snippet
  1. UPDATEdbo.DiskCapacityHistory
  2. SET     GROWTH_MOM_RAT =( SELECTCASE WHEN N.SIZE IS NULL
  3. OR N.SIZE = 0 THEN 0
  4. ELSE ( dbo.DiskCapacityHistory.SIZE
  5. - N.SIZE ) / N.SIZE
  6. END AS Growth_MOM_RAT
  7. FROM     dbo.DiskCapacityHistory N
  8. WHERE    CAST(CAST(dbo.DiskCapacityHistory.Date_CD AS CHAR(8)) AS DATE) = DATEADD(MONTH,
  9. 1,
  10. CAST(CAST(N.Date_CD AS CHAR(8)) AS DATE))
  11. AND dbo.DiskCapacityHistory.DataBaseID = N.DataBaseID
  12. AND dbo.DiskCapacityHistory.FileID = N.FileID
  13. )
  14. WHEREdbo.DiskCapacityHistory.Date_CD = CAST(REPLACE(CONVERT(VARCHAR(10), GETDATE(), 120),
  15. '-', '') AS INT)
  16. UPDATEdbo.DiskCapacityHistory
  17. SET     GROWTH_YOY_RAT =( SELECTCASE WHEN N.SIZE IS NULL
  18. OR N.SIZE = 0 THEN 0
  19. ELSE ( dbo.DiskCapacityHistory.SIZE
  20. - N.SIZE ) / N.SIZE
  21. END AS Growth_YOY_RAT
  22. FROM     dbo.DiskCapacityHistory N
  23. WHERE    CAST(CAST(dbo.DiskCapacityHistory.Date_CD AS CHAR(8)) AS DATE) = DATEADD(MONTH,
  24. 12,
  25. CAST(CAST(N.Date_CD AS CHAR(8)) AS DATE))
  26. AND dbo.DiskCapacityHistory.DataBaseID = N.DataBaseID
  27. AND dbo.DiskCapacityHistory.FileID = N.FileID
  28. )
  29. WHEREdbo.DiskCapacityHistory.Date_CD = CAST(REPLACE(CONVERT(VARCHAR(10), GETDATE(), 120),
  30. '-', '') AS INT)

Code Snippet
  1. CREATE TABLE #DiskCapacityHistory
  2. (
  3. DATE_CD INT ,
  4. DataBaseID INT ,
  5. FileID INT ,
  6. Growth_MOM_RAT FLOAT
  7. ) ;
  8. INSERTINTO #DiskCapacityHistory
  9. SELECT  M.DATE_CD ,
  10. M.DataBaseID ,
  11. M.FileID ,
  12. CASE WHEN N.SIZE IS NULL
  13. OR N.SIZE = 0 THEN 0
  14. ELSE ( M.SIZE - N.SIZE ) / N.SIZE
  15. END AS Growth_MOM_RAT
  16. FROM    dbo.DiskCapacityHistory M ,
  17. dbo.DiskCapacityHistory N
  18. WHERE   CAST(CAST(M.Date_CD AS CHAR(8)) AS DATE) = DATEADD(MONTH, 1,
  19. CAST(CAST(N.Date_CD AS CHAR(8)) AS DATE))
  20. AND M.DataBaseID = N.DataBaseID
  21. AND M.FileID = N.FileID
  22. AND M.Date_CD = CAST(REPLACE(CONVERT(VARCHAR(10), GETDATE()
  23. - 1, 120), '-', '') AS INT)
  24. UPDATE dbo.DiskCapacityHistory
  25. SET Growth_MOM_RAT = M.Growth_MOM_RAT
  26. FROM #DiskCapacityHistory M
  27. WHERE dbo.DiskCapacityHistory.DATE_CD = M.DATE_CD
  28. AND dbo.DiskCapacityHistory.DataBaseID = M.DataBaseID
  29. AND dbo.DiskCapacityHistory.FileID = M.FileID ;

2: 幸好SQL 2008还把ORACLE的MERGE的功能给模仿了过来,但是T-SQL缺少ORACLE数据库强大的分析函数LAG,如果有这个,我计算环比,同比就非常方便了,一个SQL就搞定了,下面是个例子,本想把ORACLE的SQL也做个例子展现,但是又要建表、造数,折腾起来比较麻烦。

Oracle Sample
  1. MERGE INTO DM.TM_WGGBO_IDCTOBUSVOLDTL_DAY DM
  2. USING    (
  3. SELECT *
  4. FROM (
  5. SELECT    DATE_CD,
  6. CITY_ID,
  7. IDC_NODE,
  8. VOL_TYPE,
  9. LAG(IDC_VOL_RAT   ) OVER(PARTITION BY CITY_ID,IDC_NODE,VOL_TYPE,SUBSTR(DATE_CD,7,2) ORDER BY SUBSTR(DATE_CD,0,6)) AS IDC_MOM_RAT                ,
  10. LAG(IDC_VOL_RAT   ) OVER(PARTITION BY CITY_ID,IDC_NODE,VOL_TYPE,SUBSTR(DATE_CD,5,4) ORDER BY SUBSTR(DATE_CD,0,4)) AS IDC_YOY_RAT                 ,
  11. FROM DM.TM_WGGBO_IDCTOBUSVOLDTL_DAY
  12. ) T
  13. WHERE EXISTS(SELECT 1 FROM ETL.T_IDCVOL_DAY_${ssid} WHERE DATE_CD = T.DATE_CD)
  14. ) TEMP
  15. ON (
  16. DM.DATE_CD     = TEMP.DATE_CD     AND
  17. DM.CITY_ID     = TEMP.CITY_ID     AND
  18. DM.IDC_NODE    = TEMP.IDC_NODE    AND
  19. DM.VOL_TYPE    = TEMP.VOL_TYPE
  20. )
  21. WHEN MATCHED THEN
  22. UPDATE
  23. SET DM.IDC_MOM_RAT    =       TEMP.IDC_MOM_RAT                    ,
  24. DM.IDC_YOY_RAT    =       TEMP.IDC_YOY_RAT
  25. ;
  26. COMMIT;

MS SQL 监控数据/日志文件增长相关推荐

  1. 如何使用损坏或删除SQL Server事务日志文件重建数据库

    This is the last article, but not the least one, in the SQL Server Transaction Log series. In this s ...

  2. 删除不需要的(辅助)SQL Server事务日志文件

    This article explores the use of multiple SQL Server Transaction Log Files and the process of removi ...

  3. Sql server 2005日志文件太大,使其减小的方法

    Sql server 2005日志文件太大,使其减小的方法 Sqlserver2005日志文件太大,使其减小的方法: 运行下面的三行 dbName为数据库名: backup log dbNamewit ...

  4. sql oracle 自增长字段,在Oracle、MySQL、MS SQL Server中创设自动增长字段

    在Oracle.MySQL.MS SQL Server中创建自动增长字段 好吧,今天面试有道题,要各个数据库怎么建立自增长字段,顺便复习一下吧,最近面试很多数据库问题... 一:Oracle Orac ...

  5. Zabbix监控网络设备日志文件及字段报警

    Zabbix监控网络设备日志文件及字段报警 一.首先就是配置网络设备日志传送到zabbix存放日志的指定目录,一般目录为/var/log/ 需要配置rsyslog.conf 根据需求添加tcp或者ud ...

  6. 将本地的MS SQL Server数据导入到远程服务器上

    该演示引导客户将本地的MS SQL Server数据导入到远程服务器上,供客户的网站使用. 首先登录到远程数据库服务器: 1.右击您准备导入数据的数据库,选择"所有任务"下的&qu ...

  7. nagios插件之监控MQA日志文件

    监控MQA日志文件mqsgip.log,过滤<MO-SMS> smsgw_delivery(主动上行).<MO-SMS> report(报告上行).<MT-SMS> ...

  8. ZABBIX监控JAVA日志文件

    最近开发人员有一个需求,监控java程序的报错日志,如日志中包含"ERROR"关键字的信息,就邮件告警,以下是具体实现方法. 一.创建模板 以上是已经创建好的模板,名为" ...

  9. 【电脑小技巧每日一讲:SQL server 2016日志文件的清理】

    一.问题描述 本人在使用SQL server 2016过程中不断的删除还原数据库导致积累了大量的日志文件,因此老师给我们提供了一种解决办法,用于在保留数据的情况下收缩空间. 二.解决步骤 1.获取数据 ...

最新文章

  1. AuxreRP教学网站创始人郑建国:发挥Axure和原型真正的价值
  2. windows mysql.tar安装_MySQL的安装
  3. linux shell程序设计实验报告,linux的shell脚本实验报告
  4. C#帮助控件HelpProvider的使用
  5. React开发(274):ant design table额外展开行
  6. 北美暴风雨,Linux5.12被延迟6天发布
  7. android 画笔
  8. [FFmpeg] RGBA 和 YUV 存储方式
  9. html5有哪些优点,HTML5真正的优势优点有什么?
  10. 五子棋c语言代码光标,c语言写的鼠标操作的五子棋游戏,欢迎观赏!
  11. 搜狗关键词挖掘工具,搜狗权重关键词挖掘工具
  12. php 中 normdist,说明 Excel 中的 NORMDIST 函数
  13. 【Jquery】文本框校验练习
  14. DNS劫持原理,DNS劫持如何解决?
  15. 有些事情让感情无处安放
  16. 打印1000~2000年之间的闰年
  17. 刘钰02018010219
  18. 小程序使用node.js开发后台接口
  19. 大规模数据存储技术之Erasure Code(EC编码)
  20. java内部类以及使用场景

热门文章

  1. 卡方检验chi-square test
  2. kitti数据集反代下载
  3. springboot学习过程中遇到的错误集
  4. cmd查看端口占用情况 和 关闭被占用的端口
  5. 5-9 c语言之【初识win32编程】
  6. python设计模式之猴子补丁模式
  7. 前后端分离之权限验证
  8. 黄学长模拟day1 球的序列
  9. 赤虹JSON模块 v1.0 麻雀虽小, 五脏俱全
  10. 转载 @html.ActionLink的几种参数格式