原文:SQL Server 游标运用:查看一个数据库所有表大小信息(Sizes of All Tables in a Database)

一.本文所涉及的内容(Contents)

  1. 本文所涉及的内容(Contents)
  2. 背景(Contexts)
  3. 实现代码(SQL Codes)
    1. 方法一:运用游标
    2. 方法二:运用系统存储过程
    3. 方法三:拼接SQL
  4. 参考文献(References)

二.背景(Contexts)

  在性能调优或者需要了解某数据库表信息的时候,最直观的方式就是罗列出这个数据所有表的信息,这些信息包括:表的记录数、数据记录占用空间、索引占用空间、未使用的空间等(如Figure1所示),有了这些信息你可以简单的判断这个数据库来自数据上的压力可能是某个表造成的。因为表数据越大,对数据库性能的影响越大。

  要实现某个数据库所有表的信息,可以通过游标的形式获取相应的数据,下图Figure1返回某数据库中所有表的信息:

(Figure1:某数据库所有表信息)

  也许你并不满足于Figure1的信息,你希望获取整个数据库实例中所有数据库所有表的信息(如Figure2所示),如果想了解里面的实现可以参考:SQL Server 查看所有数据库所有表大小信息(Sizes of All Tables in All Database)

(Figure2:所有数据库所有表信息)

三.实现代码(SQL Codes)

为了实现Figure1的效果,有三种方式可以实现:

  1. 运用游标循环每个表,调用系统存储过程sp_spaceused把结果保存到临时表,可以过滤表;

  2. 运用系统存储过程sp_MSforeachtable把结果保存到临时表,可以过滤表;

  3. 运用系统表INFORMATION_SCHEMA.TABLES与系统存储过程sp_spaceused结合起来,拼接出每个表的INSERT语句,把结果保存到临时表,可以过滤表;

(一) 运用游标循环每个表,调用系统存储过程sp_spaceused把结果保存到临时表,可以过滤表;

  首先定义一个临时表变量@tablespaceinfo用于保存表的信息,使用游标读取sys.tables中的表名称,再通过sp_spaceused获取这个表的相关数据插入到临时表变量@tablespaceinfo。下面是SQL脚本的实现,效果就如Figure1所示:

--Script1:
--查看某数据库所有表的信息
DECLARE @tablespaceinfo TABLE (
[name] SYSNAME,
[rows] BIGINT,
[reserved] VARCHAR(100),
[data] VARCHAR(100),
[index_size] VARCHAR(100),
[unused] VARCHAR(100)
) DECLARE @tablename VARCHAR(255); DECLARE Info_cursor CURSOR FOR
SELECT '['+[name]+']' FROM sys.tables WHERE TYPE='U'; OPEN Info_cursor
FETCH NEXT FROM Info_cursor INTO @tablename WHILE @@FETCH_STATUS = 0
BEGIN
INSERT INTO @tablespaceinfo EXEC sp_spaceused @tablename FETCH NEXT FROM Info_cursor INTO @tablename
END CLOSE Info_cursor
DEALLOCATE Info_cursor SELECT * FROM @tablespaceinfo
ORDER BY Cast(Replace(reserved,'KB','') AS INT) DESC

(二) 运用系统存储过程sp_MSforeachtable把结果保存到临时表,可以过滤表;

  下面Script2脚本是通过使用系统存储过程sp_MSforeachtable,返回的结果如Figure1所示:

--Script2:
--查看某数据库所有表的信息
DECLARE @tablespaceinfo TABLE (
[name] SYSNAME,
[rows] BIGINT,
[reserved] VARCHAR(100),
[data] VARCHAR(100),
[index_size] VARCHAR(100),
[unused] VARCHAR(100)
) INSERT INTO @tablespaceinfo EXEC sp_MSforeachtable @command1="sp_spaceused '?'" SELECT * FROM @tablespaceinfo
ORDER BY Cast(Replace(reserved,'KB','') AS INT) DESC

  1) 如果你想使用sp_MSforeachtable但是又想过滤掉一些表,你可以在查询@tablespaceinfo的时候加入Where条件(这种方式就不演示了);或者直接在开始使用sp_MSforeachtable的时候就进行过滤:

--获取所有表信息
EXEC sp_MSforeachtable @command1="sp_spaceused '?'"

如果我们加入@whereand参数进行过滤,但是会出现下图的错误信息:

--过滤某些表
EXEC sp_MSforeachtable @whereand="and [name] like 't%'", @command1="sp_spaceused '?'"

(Figure3:错误信息)

  经过查看sp_MSforeachtable的源代码,发现是有多个[name]字段的,所以指明字段,上面的错误就可以解决了,效果如下图所示。把下面的SQL代码替换Script2的部分代码就可以了。

--过滤某些表
EXEC sp_MSforeachtable @whereand="and o.[name] like 't%'", @command1="sp_spaceused '?'"
--或者
EXEC sp_MSforeachtable @whereand="and syso.[name] like 't%'", @command1="sp_spaceused '?'"

(Figure4:过滤返回的结果)

  2) 在sp_MSforeachtable系统存储过程,有@whereand的参数可以对表进行过滤,sp_MSForEachDB系统存储是否也有同样的功能呢?查看了sp_MSForEachDB的源码,我们发现是没有这个功能的,为实现这个功能,我对sp_MSForEachDB进行修改,重新命名为:sp_MSForEachDB_Filter

--扩展sp_MSforeachdb
create proc dbo.[sp_MSforeachdb_Filter]
@command1 nvarchar(2000), @replacechar nchar(1) = N'?', @command2 nvarchar(2000) = null, @command3 nvarchar(2000) = null,
@whereand nvarchar(2000) = null,@precommand nvarchar(2000) = null, @postcommand nvarchar(2000) = null
as
set deadlock_priority low declare @inaccessible nvarchar(12), @invalidlogin nvarchar(12), @dbinaccessible nvarchar(12)
select @inaccessible = ltrim(str(convert(int, 0x03e0), 11))
select @invalidlogin = ltrim(str(convert(int, 0x40000000), 11))
select @dbinaccessible = N'0x80000000' if (@precommand is not null)
exec(@precommand) declare @origdb nvarchar(128)
select @origdb = db_name()
exec(N'declare hCForEachDatabase cursor global for select name from master.dbo.sysdatabases d ' +
N' where (d.status & ' + @inaccessible + N' = 0)' +
N' and (DATABASEPROPERTY(d.name, ''issingleuser'') = 0 and (has_dbaccess(d.name) = 1))' + @whereand) declare @retval int
select @retval = @@error
if (@retval = 0)
exec @retval = sys.sp_MSforeach_worker @command1, @replacechar, @command2, @command3, 1 if (@retval = 0 and @postcommand is not null)
exec(@postcommand) declare @tempdb nvarchar(258)
SELECT @tempdb = REPLACE(@origdb, N']', N']]')
exec (N'use ' + N'[' + @tempdb + N']') return @retval

  上面的存储过程sp_MSforeachdb_Filter是依照sp_MSforeachtable进行简单修改的,创建之后就可以使用下面的SQL脚本进行过滤数据库了,效果如下图所示:

--过滤数据库
EXEC [sp_MSforeachdb_Filter] @command1="print '?'",
@whereand=" and [name] not in('tempdb','master','model','msdb') "

(Figure5:过滤数据库)

(三) 运用系统表INFORMATION_SCHEMA.TABLES与系统存储过程sp_spaceused结合起来,拼接出每个表的INSERT语句,把结果保存到临时表,可以过滤表;

  一次偶然的机会看到一个同样能实现Figure1效果的SQL脚本,它使用了系统表INFORMATION_SCHEMA.TABLES,下面是我修改过的SQL脚本,区别就在于可以满足对不同架构表的查询。原文详情可以参考:How to get information about all databases without a loop

--Script3:Sizes of All Tables in a Database
--exec sp_MSforeachtable 'print ''?'' exec sp_spaceused ''?'''
--在它的基础上做了些修改,适合不同的框架dbo等
IF OBJECT_ID('tempdb..#TablesSizes') IS NOT NULL
DROP TABLE #TablesSizes CREATE TABLE #TablesSizes (TableName sysname, Rows bigint, reserved varchar(100), data varchar(100), index_size varchar(100), unused varchar(100)) DECLARE @sql VARCHAR(MAX)
SELECT @sql = COALESCE(@sql,'') + '
INSERT INTO #TablesSizes execute sp_spaceused ''' + QUOTENAME(TABLE_SCHEMA,'[]') + '.' + QUOTENAME(Table_Name,'[]') + ''''
FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' PRINT (@SQL)
EXECUTE (@SQL) SELECT * FROM #TablesSizes ORDER BY TableName

上面PRINT出来的脚本类似下图Figure6所示:

(Figure6:拼接的SQL代码)

四.参考文献(References)

与存储过程sp_MSforeachdb类似的存储过程sp_MSforeachdb

SQL Server数据库开发顶级技巧

sp_MSforeachtable使用方法

How to get information about all databases without a loop

关于quotename的用法

SQL Server 游标运用:查看一个数据库所有表大小信息(Sizes of All Tables in a Database)的更多相关文章

  1. SQL Server 游标运用:查看所有数据库所有表大小信息(Sizes of All Tables in All Database)

    原文:SQL Server 游标运用:查看所有数据库所有表大小信息(Sizes of All Tables in All Database) 一.本文所涉及的内容(Contents) 本文所涉及的内容 ...

  2. SQL Server中怎么查看每个数据库的日志大小,以及怎么确定数据库的日志文件,怎么用语句收缩日志文件

    一,找到每个数据库的日志文件大小 SQL Server:查看SQL日志文件大小命令:dbcc sqlperf(logspace) DBA 日常管理工作中,很重要一项工作就是监视数据库文件大小,及日志文 ...

  3. 通过 SQL Server 视图访问另一个数据库服务器表的方法

    今天项目经理跑过来对我大吼大叫说什么之前安排让我做一大堆接口为什么没做,我直接火了,之前明明没有这个事情…… 不过事情还要解决,好在两个项目都是用的sqlserver,可以通过跨数据库视图来快速解决问 ...

  4. SQL Server 游标运用:查看数据库所有表大小信息

    一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 实现代码(SQL Codes) 方法一:运用游标 方法二:运用系统存储过程 方法三:拼接SQL ...

  5. SQL Server 中怎么查看一个字母的ascii编码或者Unicode编码

    参考文章:微信公众号文章 在sql中怎么查看一个字符的ascii编码,so easy !! select ASCII('a') SELECT CHAR(97) charNum SELECT UNICO ...

  6. SQL Server 中怎么查看一个字母的ascii编码或者Unicode编码(转载)

    在sql中怎么查看一个字符的ascii编码或Unicode编码: SELECT ASCII('a') AS [AsciiNum]--字符获取ASCII码 SELECT UNICODE(N'a') AS ...

  7. SQL Server和MySql获取当前数据库每个表的列数

    Sql server:(连接数据库后,点击当前数据库再新建查询) select count(c.name),o.name from syscolumns c left join sysobjects ...

  8. 如何隐藏掉SQL Server中自带系统数据库,数据表,存储过程等显示文件,只显示用户的数据库,数据表等文件

    企业管理器了,---->   编辑该数据库的注册属性--->“常规”属性页下面-->“显示系统数据库和系统对象”的选项去掉

  9. SQL SERVER 性能优化二: 数据库初始值大小及增长方式设置

    数据库增长方式主要有两种,按百分比自动增长和按固定大小自动增长,设置初始大小和增长方式需谨慎. 初始大小就是建库的大小,设小了,容易造成磁盘碎片,频繁增长也会影响IO响应.设大了,也不行,设大了,每次 ...

随机推荐

  1. B/S系统的前台和后台数据转递机制探究

    作者:朱金灿 来源:http://blog.csdn.net/clever101 说实话写这篇文章超出了我的能力范围之外(因为我并没有多少Web开发经验),我所期待的是能起一个抛砖引玉的作用--希望高 ...

  2. 正則表達式基础及java使用

    正則表達式基础 正則表達式语法(1)     普通字符:字母,数字.汉子,下划线以及没有特殊定义的标点符号都是"普通字符".表达式中的普通字符.在匹配一个字符串的时候,匹配与之同样 ...

  3. hdu 1292 "下沙野骆驼"ACM夏令营 (递推)

    "下沙野骆驼"ACM夏令营 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/ ...

  4. 为何放弃 C++ 的工作(开发慢,难度高。完全不适应互联网的快速迭代的思想)

    happypeter,2015年1月9日 昨天进燕山大学编程爱好者 QQ 群,看到有很多同学在学 C++ ,我当然是不喜欢了,因为我是做 Web 开发的嘛.所以怀着猥琐的心情,今天写篇傻傻的文章,来黑 ...

  5. 使用Ant包装时,包javax.servlet.http有没有搞错

    明确,出现此错误的原因是缺乏相应的jar包.详细原因因为servlet和JSP不是Java平台JavaSE(标准版)的一部分.而是Java EE(企业版)的一部分,因此,必须告知编译器servlet的 ...

  6. zookeeper 分布式安装/配置/启动

    版本3.4.10,已提前配置好jdk 三台主机:hadoop002,hadoop003.hadoop004 1.配置 将zookeeper-3.4.10.tar.gz解压后进入zookeeper-3. ...

  7. C# 从零开始写 SharpDx 应用 控制台创建 Sharpdx 窗口

    原文:C# 从零开始写 SharpDx 应用 控制台创建 Sharpdx 窗口 版权声明:博客已迁移到 http://lindexi.gitee.io 欢迎访问.如果当前博客图片看不到,请到 http ...

  8. Stompjs websocket vue

    公司项目要求要有消息提醒机制 , 多方面考虑用了ActiveMQ ,基本上现在主流的后台语言都没啥问题 , php phthon java nodejs , 等等都没问题 , 各位道友可以去查阅相关资 ...

  9. Android桌面悬浮窗效果实现,仿360手机卫士悬浮窗效果

    大家好,今天给大家带来一个仿360手机卫士悬浮窗效果的教程,在开始之前请允许我说几句不相干的废话. 不知不觉我发现自己接触Android已有近三个年头了,期间各种的成长少不了各位高手的帮助,总是有很多 ...

  10. listview选中滑动时背景变黑

    喵的今天调这个一直以为是背景色的问题,花了好多时间 下面才是解决方法:转自:http://daijun74.iteye.com/blog/1175143 手指在ListView上下滚动时,ListVi ...