如何计算SQL Server 2005中存储过程的SIZE?

时间:2008-10-20 19:29:05

标签: sql-server-2005 tsql stored-procedures

我被要求对特定数据库中使用的空间进行全面细分。 我知道我可以在SQL Server 2005中使用 sys.dm_db_partition_stats 来计算数据库中每个的空间大小,但有没有办法确定个人和数据库中存储过程的总大小? (当然,没有打开每一个并计算字符。)

存储过程使用的总空间不太可能很大(与实际的数据相比),但有数百个,它可能会累加。

5 个答案:

答案 0 :(得分:12)

;WITH ROUTINES AS (
    -- CANNOT use INFORMATION_SCHEMA.ROUTINES because of 4000 character limit
    SELECT o.type_desc AS ROUTINE_TYPE
            ,o.[name] AS ROUTINE_NAME
            ,m.definition AS ROUTINE_DEFINITION
    FROM sys.sql_modules AS m
    INNER JOIN sys.objects AS o
        ON m.object_id = o.object_id
)
SELECT SUM(LEN(ROUTINE_DEFINITION))
FROM ROUTINES

答案 1 :(得分:3)

比计算字符稍微好一点的方法是使用信息schema.routines。您可以将每个例程定义的长度相加为(注意每个例程定义最多为4,000个字符,请参阅下面的没有此限制的方法):

select Sum(Len(Routine_Definition)) from information_schema.routines 
where routine_type = 'PROCEDURE'

或者你可以返回每个sp的长度

select Len(Routine_Definition), * from information_schema.routines 
where routine_type = 'PROCEDURE'

存储过程的长度不太可能是问题所在。通常用数据库耗尽空间是因为没有备份日志文件(然后使用dbcc shrinkfile或dbcc shrinkdatabase缩小它)。

在Sql 2000中,这是一个例程,它提供的长度没有上面的4000个字符限制:

DECLARE @Name VarChar(250)
DECLARE RoutineCursor CURSOR FOR
   select Routine_Name from information_schema.routines where routine_type = 'PROCEDURE'

DECLARE @Results TABLE
   (   SpName   VarChar(250),
       SpLength   Int
   )

CREATE TABLE ##SpText
   (   SpText   VarChar(8000)   )

OPEN RoutineCursor
FETCH NEXT FROM RoutineCursor INTO @Name

WHILE @@FETCH_STATUS = 0
   BEGIN
      INSERT INTO ##SpText   (SpText)   EXEC sp_helptext @Name

      INSERT INTO @Results (SpName, SpLength) (SELECT @Name, Sum(Len(SpText)) FROM ##SpText)
      TRUNCATE TABLE ##SpText

      FETCH NEXT FROM RoutineCursor INTO @Name
   END

CLOSE RoutineCursor
DEALLOCATE RoutineCursor
DROP TABLE ##SpText

SELECT SpName, SpLength FROM @Results ORDER BY SpLength DESC
SELECT Sum(SpLength) FROM @Results

答案 2 :(得分:2)

Dave_H的解决方案在information_schema.routines表中达到了4,000个字符的限制

试试这个,首先生成一个带有sprocs全文的表,然后对字符长度求和。

--create a temp table to hold the data
create table ##sptext (sptext varchar(1000))
go

--generate the code to insert the full text of your sprocs
select 'insert into ##sptext (sptext) exec sp_helptext '''+specific_name+''';'
from information_schema.routines 
where routine_type = 'PROCEDURE'
go

/*Copy the output back to your query analyzer and run it*/

--now sum the results    
select sum(len(sptext))
from ##sptext

答案 3 :(得分:2)

需要使用DATALENGTH而不是LEN来获取​​字节数而不是字符数,因为sys.sql_modules目录视图的定义列是NVARCHAR(MAX),即Unicode

SELECT Type,
   SUM(Chars)  SizeChars,
   SUM(Bytes)  SizeBytes,
   SUM(Bytes) / 1024. SizeKB,
   CAST(SUM(Bytes) / 1024 AS VARCHAR) + '.' + CAST(SUM(Bytes) % 1024 AS VARCHAR) SizeKBRemBytes
FROM
(
SELECT o.type_desc Type, 
       LEN(sm.definition) Chars,
       DATALENGTH(sm.definition) Bytes
    FROM sys.sql_modules sm
    JOIN sys.objects o ON sm.object_id = o.object_id
) x
GROUP BY Type
ORDER BY Type

答案 4 :(得分:0)

改善Cade Roux答案:

/*
<documentation>
  <summary>Count size in bytes veiws, triggers, procedures and function in database.</summary>
  <returns>1 data set: RoutinType, SUM LENGTH of objects, SUM DATALENGTH.</returns>
  <issues>No</issues>
  <author>Cade Roux</author>
  <created>2008-10-20</created>
  <modified>2019-06-26 by Konstantin Taranov</modified>
  <version>1.0</version>
  <sourceLink>https://github.com/ktaranov/sqlserver-kit/blob/master/Scripts/Objects_Size_In_Database.sql</sourceLink>
  <originalLink>https://stackoverflow.com/a/219740/2298061</originalLink>
</documentation>
*/

SET NOCOUNT ON;
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

WITH CTE_Routine AS (
    /* Can not use INFORMATION_SCHEMA.ROUTINES because of 4000 character limit */
    SELECT o.type_desc     AS RoutineType
         , o.[name]        AS RoutineName
         , m.[definition]  AS RoutineDefinition
    FROM   sys.sql_modules AS m 
    INNER JOIN sys.objects AS o ON m.object_id = o.object_id
)
SELECT RoutineType
     , SUM(LEN(RoutineDefinition))            AS RoutineLen
     /* DATALENGTH for counting trailing space in the end of objects definitions */
     , SUM(DATALENGTH(RoutineDefinition)) / 2 AS RoutineDatalength
FROM   CTE_Routine
GROUP BY RoutineType;