1
0

view_CompressionGains_singleDS.sql 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. -- 2010-09-22 Pedro Lopes (Microsoft) [email protected] (http://aka.ms/sqlinsights)
  2. --
  3. -- 2013-12-03 Fixed divide by zero error
  4. --
  5. -- Recomends type of compression per object - all more trustworthy as instance uptime increases.
  6. --
  7. -- [Percent_Update]
  8. -- The percentage of update operations on a specific table, index, or partition, relative to total operations on that object. The lower the value of U (that is, the table, index, or partition is infrequently updated), the better candidate it is for page compression.
  9. --
  10. -- [Percent_Scan]
  11. -- The percentage of scan operations on a table, index, or partition, relative to total operations on that object. The higher the value of Scan (that is, the table, index, or partition is mostly scanned), the better candidate it is for page compression.
  12. --
  13. -- [Compression_Type_Recommendation] - READ DataCompression Best Practises before implementing.
  14. -- When ? means ROW if object suffers mainly UPDATES, PAGE if mainly INSERTS
  15. -- When NO_GAIN means that according to sp_estimate_data_compression_savings no space gains will be attained when compressing.
  16. --
  17. -- based on Data Compression Whitepaper at http://msdn.microsoft.com/en-us/library/dd894051(SQL.100).aspx
  18. --
  19. -- General algorithm validated by Paul Randall IF ENOUGH CPU AND RAM AVAILABLE.
  20. --
  21. SET NOCOUNT ON;
  22. CREATE TABLE ##tmpCompression ([Schema] sysname,
  23. [Table_Name] sysname,
  24. [Index_Name] sysname NULL,
  25. [Partition] int,
  26. [Index_ID] int,
  27. [Index_Type] VARCHAR(12),
  28. [Percent_Scan] smallint,
  29. [Percent_Update] smallint,
  30. [ROW_estimate_Pct_of_orig] smallint,
  31. [PAGE_estimate_Pct_of_orig] smallint,
  32. [Compression_Type_Recommendation] VARCHAR(7)
  33. );
  34. CREATE TABLE ##tmpEstimateRow (
  35. objname sysname,
  36. schname sysname,
  37. indid int,
  38. partnr int,
  39. size_cur bigint,
  40. size_req bigint,
  41. sample_cur bigint,
  42. sample_req bigint
  43. );
  44. CREATE TABLE ##tmpEstimatePage (
  45. objname sysname,
  46. schname sysname,
  47. indid int,
  48. partnr int,
  49. size_cur bigint,
  50. size_req bigint,
  51. sample_cur bigint,
  52. sample_req bigint
  53. );
  54. INSERT INTO ##tmpCompression ([Schema], [Table_Name], [Index_Name], [Partition], [Index_ID], [Index_Type], [Percent_Scan], [Percent_Update])
  55. SELECT s.name AS [Schema], o.name AS [Table_Name], x.name AS [Index_Name],
  56. i.partition_number AS [Partition], i.index_id AS [Index_ID], x.type_desc AS [Index_Type],
  57. i.range_scan_count * 100.0 / (i.range_scan_count + i.leaf_insert_count + i.leaf_delete_count + i.leaf_update_count + i.leaf_page_merge_count + i.singleton_lookup_count) AS [Percent_Scan],
  58. i.leaf_update_count * 100.0 / (i.range_scan_count + i.leaf_insert_count + i.leaf_delete_count + i.leaf_update_count + i.leaf_page_merge_count + i.singleton_lookup_count) AS [Percent_Update]
  59. FROM sys.dm_db_index_operational_stats (db_id(), NULL, NULL, NULL) i
  60. INNER JOIN sys.objects o ON o.object_id = i.object_id
  61. INNER JOIN sys.schemas s ON o.schema_id = s.schema_id
  62. INNER JOIN sys.indexes x ON x.object_id = i.object_id AND x.index_id = i.index_id
  63. WHERE (i.range_scan_count + i.leaf_insert_count + i.leaf_delete_count + leaf_update_count + i.leaf_page_merge_count + i.singleton_lookup_count) <> 0
  64. AND objectproperty(i.object_id,'IsUserTable') = 1
  65. ORDER BY [Table_Name] ASC;
  66. DECLARE @schema sysname, @tbname sysname, @ixid int
  67. DECLARE cur CURSOR FAST_FORWARD FOR SELECT [Schema], [Table_Name], [Index_ID] FROM ##tmpCompression
  68. OPEN cur
  69. FETCH NEXT FROM cur INTO @schema, @tbname, @ixid
  70. WHILE @@FETCH_STATUS = 0
  71. BEGIN
  72. --SELECT @schema, @tbname
  73. INSERT INTO ##tmpEstimateRow
  74. EXEC ('sp_estimate_data_compression_savings ''' + @schema + ''', ''' + @tbname + ''', ''' + @ixid + ''', NULL, ''ROW''' );
  75. INSERT INTO ##tmpEstimatePage
  76. EXEC ('sp_estimate_data_compression_savings ''' + @schema + ''', ''' + @tbname + ''', ''' + @ixid + ''', NULL, ''PAGE''');
  77. FETCH NEXT FROM cur INTO @schema, @tbname, @ixid
  78. END
  79. CLOSE cur
  80. DEALLOCATE cur;
  81. --SELECT * FROM ##tmpEstimateRow
  82. --SELECT * FROM ##tmpEstimatePage;
  83. WITH tmp_CTE (objname, schname, indid, pct_of_orig_row, pct_of_orig_page)
  84. AS (SELECT tr.objname, tr.schname, tr.indid,
  85. (tr.sample_req*100)/CASE WHEN tr.sample_cur = 0 THEN 1 ELSE tr.sample_cur END AS pct_of_orig_row,
  86. (tp.sample_req*100)/CASE WHEN tp.sample_cur = 0 THEN 1 ELSE tp.sample_cur END AS pct_of_orig_page
  87. FROM ##tmpEstimateRow tr INNER JOIN ##tmpEstimatePage tp ON tr.objname = tp.objname
  88. AND tr.schname = tp.schname AND tr.indid = tp.indid AND tr.partnr = tp.partnr)
  89. UPDATE ##tmpCompression
  90. SET [ROW_estimate_Pct_of_orig] = tcte.pct_of_orig_row, [PAGE_estimate_Pct_of_orig] = tcte.pct_of_orig_page
  91. FROM tmp_CTE tcte, ##tmpCompression tcomp
  92. WHERE tcte.objname = tcomp.Table_Name AND
  93. tcte.schname = tcomp.[Schema] AND
  94. tcte.indid = tcomp.Index_ID;
  95. WITH tmp_CTE2 (Table_Name, [Schema], Index_ID, [Compression_Type_Recommendation])
  96. AS (SELECT Table_Name, [Schema], Index_ID,
  97. CASE WHEN [ROW_estimate_Pct_of_orig] >= 100 AND [PAGE_estimate_Pct_of_orig] >= 100 THEN 'NO_GAIN'
  98. WHEN [Percent_Update] >= 10 THEN 'ROW'
  99. WHEN [Percent_Scan] <= 1 AND [Percent_Update] <= 1 AND [ROW_estimate_Pct_of_orig] < [PAGE_estimate_Pct_of_orig] THEN 'ROW'
  100. WHEN [Percent_Scan] <= 1 AND [Percent_Update] <= 1 AND [ROW_estimate_Pct_of_orig] > [PAGE_estimate_Pct_of_orig] THEN 'PAGE'
  101. WHEN [Percent_Scan] >= 60 AND [Percent_Update] <= 5 THEN 'PAGE'
  102. WHEN [Percent_Scan] <= 35 AND [Percent_Update] <= 5 THEN '?'
  103. ELSE 'ROW'
  104. END
  105. FROM ##tmpCompression)
  106. UPDATE ##tmpCompression
  107. SET [Compression_Type_Recommendation] = tcte2.[Compression_Type_Recommendation]
  108. FROM tmp_CTE2 tcte2, ##tmpCompression tcomp2
  109. WHERE tcte2.Table_Name = tcomp2.Table_Name AND
  110. tcte2.[Schema] = tcomp2.[Schema] AND
  111. tcte2.Index_ID = tcomp2.Index_ID;
  112. SET NOCOUNT ON;
  113. DECLARE @UpTime VARCHAR(12), @StartDate DATETIME, @sqlmajorver int, @sqlcmd NVARCHAR(500), @params NVARCHAR(500)
  114. SELECT @sqlmajorver = CONVERT(int, (@@microsoftversion / 0x1000000) & 0xff);
  115. IF @sqlmajorver = 9
  116. BEGIN
  117. SET @sqlcmd = N'SELECT @StartDateOUT = login_time, @UpTimeOUT = DATEDIFF(mi, login_time, GETDATE()) FROM master..sysprocesses WHERE spid = 1';
  118. END
  119. ELSE
  120. BEGIN
  121. SET @sqlcmd = N'SELECT @StartDateOUT = sqlserver_start_time, @UpTimeOUT = DATEDIFF(mi,sqlserver_start_time,GETDATE()) FROM sys.dm_os_sys_info';
  122. END
  123. SET @params = N'@StartDateOUT DATETIME OUTPUT, @UpTimeOUT VARCHAR(12) OUTPUT';
  124. EXECUTE sp_executesql @sqlcmd, @params, @StartDateOUT=@StartDate OUTPUT, @UpTimeOUT=@UpTime OUTPUT;
  125. SELECT @StartDate AS Collecting_Data_Since, * FROM ##tmpCompression;
  126. DROP TABLE ##tmpCompression
  127. DROP TABLE ##tmpEstimateRow
  128. DROP TABLE ##tmpEstimatePage;
  129. GO