设为首页 收藏本站
查看: 858|回复: 0

[经验分享] SQL Server 中统计各用户表记录条数 的两种方法

[复制链接]

尚未签到

发表于 2015-6-27 16:41:48 | 显示全部楼层 |阅读模式
  最近做数据监控遇到这么个查询需求,就从系统存储过程[sys].[sp_tables]中征用了遍历用户表的代码,组织一下,配合以MSSQL 中的表变量,写了如下代码:
方法一:



    DECLARE @NAME VARCHAR(50)
    DECLARE @SQL VARCHAR(1000)
   
    SET @SQL = '        
    DECLARE @RESULT_TABLE TABLE
    (
        [TableName]        VARCHAR(32),
        [RowCount]        INT
    )
    DECLARE @TEMP_COUNT INT'
   
    DECLARE TB_CURSOR CURSOR FOR  

    SELECT
        TABLE_NAME      = CONVERT(SYSNAME,O.NAME)
    FROM
        SYS.ALL_OBJECTS O
    WHERE
        O.TYPE = 'U' AND
        HAS_PERMS_BY_NAME(QUOTENAME(SCHEMA_NAME(O.SCHEMA_ID)) + '.' + QUOTENAME(O.NAME),
                          'OBJECT',
                          'SELECT') = 1
   
    OPEN TB_CURSOR   
    FETCH NEXT FROM TB_CURSOR INTO @NAME   

    WHILE @@FETCH_STATUS = 0   
    BEGIN   
           SET @SQL = @SQL + CHAR(10) + 'INSERT INTO @RESULT_TABLE SELECT ' + '''' + @NAME +  '''' + ',COUNT(1) FROM ' + @NAME + ';'
        
           FETCH NEXT FROM TB_CURSOR INTO @NAME   
    END

    CLOSE TB_CURSOR
    DEALLOCATE TB_CURSOR
   
    SET @SQL = @SQL + CHAR(10) +'SELECT * FROM @RESULT_TABLE '
    EXEC (@SQL)
          
  这里使用表变量而非临时表,是因为大多数数据库中表的数量不会太多,使得临时表(或表变量)中的记录条数不会很多。如此一来,借以表变量,将数据暂时存放放在内存中要比存放在tempDB中更加高效。
  
  基本思路为:
  1.从系统视图SYS.ALL_OBJECTS中取出所有用户表的表名。
  2.用游标遍历所有表名,并使用select count(1)来统计该表行数,并拼接成相应的暂存SQL代码。
  3.执行生成的SQL代码,取得数据结果集。其中生成的SQL代码为:


    DECLARE @RESULT_TABLE TABLE
    (
        [TableName]        VARCHAR(32),
        [RowCount]        INT
    )
    DECLARE @TEMP_COUNT INT
   
    -- each tables
    INSERT INTO @RESULT_TABLE SELECT 'LDMMessage',COUNT(1) FROM LDMMessage;
    INSERT INTO @RESULT_TABLE SELECT 'DCSFile',COUNT(1) FROM DCSFile;
    INSERT INTO @RESULT_TABLE SELECT 'SSRCode',COUNT(1) FROM SSRCode;
    INSERT INTO @RESULT_TABLE SELECT 'PRLMessage',COUNT(1) FROM PRLMessage;
    ...
   
    SELECT * FROM @RESULT_TABLE   
  写完之后,感觉毕竟使用到了游标和表变量,性能不太理想,应该还有更好的方法,便google了一下,发现也可以从系统视图SYS.SYSOBJECTS中查出用户表名,并使用主键ID连接视图SYS.SYSINDEXES,根据索引的相关数据来获得表的记录条数:
方法二:


    DECLARE @RESULT_TABLE TABLE
    (
        [TableName]        VARCHAR(32),
        [RowCount]        INT
    )

    INSERT INTO
        @RESULT_TABLE
    SELECT
        O.NAME, I.ROWCNT
    FROM
        SYS.SYSOBJECTS O, SYSINDEXES I
    WHERE
        O.ID = I.ID AND
        O.XTYPE = 'U' AND
        I.INDID < 2

    SELECT * FROM @RESULT_TABLE
          
  这里主要使用了SYS.SYSOBJECTS和SYS.SYSINDEXES的连接,并通过 I.INDID < 2 条件找到表的聚集索引或堆记录(Heap:0, 聚集索引:1,非聚集索引>1),由此得出Data级别的记录条数RowCnt。
  
性能对比:
  使用SQL Server Profiler来检测两种方法的执行开销,结果如下:
DSC0000.png
  方法一开销62个CPU时间片,而方法二之开销了2个时间片,性能大为胜出。
  
参考资料:
  http://msdn.microsoft.com/en-us/library/ms190324.aspx
  http://msdn.microsoft.com/en-us/library/ms178618.aspx
  http://msdn.microsoft.com/en-us/library/ms190283.aspx
  

DSC0001.gif DSC0002.gif [sys].[sp_tables]


/****** Object:  StoredProcedure [sys].[sp_tables]    Script Date: 10/27/2010 14:06:19 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER procedure [sys].[sp_tables]
(
    @table_name         nvarchar(384)   = null,
    @table_owner        nvarchar(384)   = null,
    @table_qualifier    sysname = null,
    @table_type         varchar(100) = null,
    @fUsePattern        bit = 1 -- To allow users to explicitly disable all pattern matching.
)
as
    declare @type1      varchar(3)
    declare @qual_name  nvarchar(517) -- [schema].[table]
    declare @table_id   int

    if @table_qualifier = '%' and @table_owner = '' and @table_name = ''
    begin
        -- Debug output, do not remove it.
        -- print 'Special feature #1:  enumerate databases when owner and name are blank but qualifier is explicitly "%".'
        select
            TABLE_QUALIFIER = convert(sysname,d.name),
            TABLE_OWNER     = convert(sysname,null),
            TABLE_NAME      = convert(sysname,null),
            TABLE_TYPE      = convert(varchar(32),null),
            REMARKS         = convert(varchar(254),null)    -- Remarks are NULL.
        from
            sys.databases d
        where
            d.name  'model' -- eliminate MODEL database
        order by 1
        return
    end

    if @table_qualifier = '' and @table_owner = '%' and @table_name = ''
    begin
        -- Debug output, do not remove it.
        -- print 'Special feature #2:  enumerate owners when qualifier and name are blank but owner is explicitly "%".
        select distinct
            TABLE_QUALIFIER = convert(sysname,null),
            TABLE_OWNER     = convert(sysname,schema_name(o.schema_id)),
            TABLE_NAME      = convert(sysname,null),
            TABLE_TYPE      = convert(varchar(32),null),
            REMARKS         = convert(varchar(254),null)    -- Remarks are NULL.
        from
            sys.all_objects o
        where
            o.type in ('S','U','V')  -- limit columns to tables and views only
        order by 2
        return
    end

    if @table_qualifier = '' and @table_owner = '' and @table_name = '' and @table_type = '%'
    begin
        -- Debug output, do not remove it.
        -- print 'Special feature #3:  enumerate table types when qualifier, owner and name are blank but table type is explicitly "%".'
        select
            TABLE_QUALIFIER = convert(sysname,null),
            TABLE_OWNER     = convert(sysname,null),
            TABLE_NAME      = convert(sysname,null),
            TABLE_TYPE      = convert(varchar(32),
                                        rtrim(substring('SYSTEM TABLETABLE       VIEW',(c.column_id-1)*12+1,12))),
            REMARKS         = convert(varchar(254),null)    -- Remarks are NULL.
        from
            sys.all_objects o,
            sys.all_columns c
        where
            o.object_id = c.object_id and o.object_id = object_id('sysusers') and
            c.column_id

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-81010-1-1.html 上篇帖子: Sql Server之旅——第七站 为什么都说状态少的字段不能建索引 下篇帖子: SQL Server 性能调优(内存)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表