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

本文涉及的产品
云数据库 RDS SQL Server,基础系列 2核4GB
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
简介: 原文:SQL Server 游标运用:查看一个数据库所有表大小信息(Sizes of All Tables in a Database)一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 实现代码(SQL Codes)方法一:运用游...
原文: 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返回某数据库中所有表的信息:

image

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

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

F2

(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 '?'"

clip_image001[1]

(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 '?'"

clip_image002[3]

(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') "

clip_image003[1]

(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语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情: https://www.aliyun.com/product/rds/sqlserver
目录
相关文章
|
11天前
|
SQL 数据库
数据库数据恢复—SQL Server报错“错误 823”的数据恢复案例
SQL Server数据库附加数据库过程中比较常见的报错是“错误 823”,附加数据库失败。 如果数据库有备份则只需还原备份即可。但是如果没有备份,备份时间太久,或者其他原因导致备份不可用,那么就需要通过专业手段对数据库进行数据恢复。
|
19天前
|
SQL 开发框架 .NET
【YashanDB 知识库】使用 c- 调用 yashandb odbc 驱动执行 SQL 时报 YAS-08008 not all variables bounded
某客户C# ASP.NET应用在使用yashandb ODBC驱动时,因驱动不支持绑定变量执行SQL语句而报错“YAS-08008 not all variables bounded”,导致应用无法正常运行。影响所有yashandb及ODBC驱动版本。解决方法为避免使用绑定变量或升级驱动版本。通过简化场景成功复现问题。
|
1月前
|
SQL 存储 关系型数据库
【SQL技术】不同数据库引擎 SQL 优化方案剖析
不同数据库系统(MySQL、PostgreSQL、Doris、Hive)的SQL优化策略。存储引擎特点、SQL执行流程及常见操作(如条件查询、排序、聚合函数)的优化方法。针对各数据库,索引使用、分区裁剪、谓词下推等技术,并提供了具体的SQL示例。通用的SQL调优技巧,如避免使用`COUNT(DISTINCT)`、减少小文件问题、慎重使用`SELECT *`等。通过合理选择和应用这些优化策略,可以显著提升数据库查询性能和系统稳定性。
86 9
|
2月前
|
SQL Java 数据库连接
【潜意识Java】MyBatis中的动态SQL灵活、高效的数据库查询以及深度总结
本文详细介绍了MyBatis中的动态SQL功能,涵盖其背景、应用场景及实现方式。
151 6
|
3月前
|
SQL Oracle 数据库
使用访问指导(SQL Access Advisor)优化数据库业务负载
本文介绍了Oracle的SQL访问指导(SQL Access Advisor)的应用场景及其使用方法。访问指导通过分析给定的工作负载,提供索引、物化视图和分区等方面的优化建议,帮助DBA提升数据库性能。具体步骤包括创建访问指导任务、创建工作负载、连接工作负载至访问指导、设置任务参数、运行访问指导、查看和应用优化建议。访问指导不仅针对单条SQL语句,还能综合考虑多条SQL语句的优化效果,为DBA提供全面的决策支持。
105 11
|
3月前
|
SQL 关系型数据库 MySQL
MySQL导入.sql文件后数据库乱码问题
本文分析了导入.sql文件后数据库备注出现乱码的原因,包括字符集不匹配、备注内容编码问题及MySQL版本或配置问题,并提供了详细的解决步骤,如检查和统一字符集设置、修改客户端连接方式、检查MySQL配置等,确保导入过程顺利。
|
3月前
|
SQL 监控 安全
SQL Servers审核提高数据库安全性
SQL Server审核是一种追踪和审查SQL Server上所有活动的机制,旨在检测潜在威胁和漏洞,监控服务器设置的更改。审核日志记录安全问题和数据泄露的详细信息,帮助管理员追踪数据库中的特定活动,确保数据安全和合规性。SQL Server审核分为服务器级和数据库级,涵盖登录、配置变更和数据操作等事件。审核工具如EventLog Analyzer提供实时监控和即时告警,帮助快速响应安全事件。
|
4月前
|
SQL 存储 BI
gbase 8a 数据库 SQL合并类优化——不同数据统计周期合并为一条SQL语句
gbase 8a 数据库 SQL合并类优化——不同数据统计周期合并为一条SQL语句
|
存储 SQL 程序员
【Sql Server】存储过程通过作业定时执行按天统计记录
通过前两篇文章的学习,我们已经对创建表、存储过程、作业等功能点有所了解 本次将结合前面所学习的知识点,创建统计表以及结合作业定时按天以及实时统计域名各个长度的记录值
445 0
【Sql Server】存储过程通过作业定时执行按天统计记录
|
存储 SQL 数据库
SQL Server——为什么要使用存储过程?不使用是什么样的?
提高数据库执行速度,可能第一次见到这句话的小伙伴们感觉到非常的匪夷所思叭!怎么就提高了它的执行速度捏,从哪方面可以表现出来呢?既然这里要说到的是为什么要使用存储过程,也就是说它的优点是什么。那我们肯定就要对使用和不使用存储过程两方面来进行对比才能看出它的优点对吧。

热门文章

最新文章