数据库干货:SQLServer运维实用的几个脚本

2024-08-27 10:50:14 浏览数 (2)

1、查询出最近所有耗时最大的SQL语句

返回的是未关联任何特定对象的最耗费资源的查询信息,包括查询的执行SQL、最后一次执行的总耗时、所有执行的总耗时、执行最小耗时、执行最大耗时、执行次数、计划生成次数、所有执行期间总共读取和写的物理磁盘次数以及逻辑磁盘次数等信息。

代码语言:javascript复制
SELECT s2.dbid,
       s1.sql_handle,
       (
           SELECT TOP 1
                  SUBSTRING(   s2.text,
                               statement_start_offset / 2   1,
                               ((CASE
                                     WHEN statement_end_offset = -1 THEN
                               (LEN(CONVERT(NVARCHAR(MAX), s2.text)) * 2)
                                     ELSE
                                         statement_end_offset
                                 END
                                ) - statement_start_offset
                               ) / 2   1
                           )
       ) AS 执行SQL,
       last_worker_time '最后执行总耗时(毫秒)',
       last_execution_time '最后执行时间',
       total_worker_time '所有执行总耗时(毫秒)',
       min_worker_time '执行最小耗时(毫秒)',
       max_worker_time '执行最大耗时(毫秒)',
       execution_count,
       plan_generation_num,
       total_physical_reads,
       last_physical_reads,
       min_physical_reads,
       max_physical_reads,
       total_logical_writes,
       last_logical_writes,
       min_logical_writes,
       max_logical_writes
FROM sys.dm_exec_query_stats AS s1
    CROSS APPLY sys.dm_exec_sql_text(sql_handle) AS s2
WHERE s2.objectid IS NULL
ORDER BY last_worker_time DESC,
         s1.sql_handle,
         s1.statement_start_offset,
         s1.statement_end_offset;

说明

列名

描述

s2.dbid

执行查询的数据库ID

s1.sql_handle

SQL语句的唯一标识符

执行SQL

通过sys.dm_exec_sql_text获取的SQL语句文本

last_worker_time

上一次执行查询所花费的总CPU时间(毫秒)

last_execution_time

查询最后一次执行的时间

total_worker_time

所有执行查询所花费的总CPU时间(毫秒)

min_worker_time

任何单次执行查询所花费的最少CPU时间(毫秒)

max_worker_time

任何单次执行查询所花费的最大CPU时间(毫秒)

execution_count

查询被执行的次数

plan_generation_num

计划生成次数

total_physical_reads

所有执行期间总共读取的物理磁盘次数

last_physical_reads

上一次执行期间读取的物理磁盘次数

min_physical_reads

任何单次执行期间最少读取的物理磁盘次数

max_physical_reads

任何单次执行期间最多读取的物理磁盘次数

total_logical_writes

所有执行期间总共写的逻辑磁盘次数

last_logical_writes

上一次执行期间写的逻辑磁盘次数

min_logical_writes

任何单次执行期间最少写的逻辑磁盘次数

max_logical_writes

任何单次执行期间最多的逻辑磁盘次数

● sys.dm_exec_query_stats AS s1:SQL Server中的系统视图,提供了关于查询统计信息,例如CPU时间、读取次数和写入次数等。

● CROSS APPLY sys.dm_exec_sql_text(s1.sql_handle) AS s2:使用CROSS APPLY运算符将s1.sql_handle传递给s2,以便从sys.dm_exec_sql_text视图中检索实际的SQL文本

2、查询数据库每个数据表存储占用

查询指定数据库的记录数、总工占用空间KB、总共占用空间MB、已使用空间KB、已使用空间MB、未使用空间KB、未使用空间MB,这对于分析磁盘占用非常有用。

代码语言:javascript复制
SELECT
	t.NAME AS 表名,
	s.Name AS 架构,
	p.rows AS 记录数,
	SUM ( a.total_pages ) * 8 AS 总工占用空间KB,
	CAST ( ROUND( ( ( SUM ( a.total_pages ) * 8 ) / 1024.00 ), 2 ) AS NUMERIC ( 36, 2 ) ) AS 总共占用空间MB,
	SUM ( a.used_pages ) * 8 AS 已使用空间KB,
	CAST ( ROUND( ( ( SUM ( a.used_pages ) * 8 ) / 1024.00 ), 2 ) AS NUMERIC ( 36, 2 ) ) AS 已使用空间MB,
	( SUM ( a.total_pages ) - SUM ( a.used_pages ) ) * 8 AS 未使用空间KB,
	CAST (
		ROUND( ( ( SUM ( a.total_pages ) - SUM ( a.used_pages ) ) * 8 ) / 1024.00, 2 ) AS NUMERIC ( 36, 2 ) 
	) AS 未使用空间MB 
FROM	sys.tables t
INNER JOIN sys.indexes i ON t.OBJECT_ID = i.object_id
INNER JOIN sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
INNER JOIN sys.allocation_units a ON p.partition_id = a.container_id
LEFT OUTER JOIN sys.schemas s ON t.schema_id = s.schema_id 
WHERE	t.NAME NOT LIKE 'dt%' AND t.is_ms_shipped = 0 AND i.OBJECT_ID > 0 
GROUP BY	t.Name,s.Name,p.Rows 
ORDER BY 总共占用空间MB DESC;

3、当前正在执行的最耗时的前10个SQL语句

该语句适合排查生产环境实时SQL语句慢的情况。

代码语言:javascript复制
SELECT TOP 10 
    r.session_id,
    r.request_id,
    r.start_time AS '开始时间',
    r.status AS '状态',
    r.command AS '命令',
    t.text AS 'sql语句',
    DB_NAME(r.database_id) AS '数据库名',
    r.blocking_session_id AS '正在阻塞其他会话的会话ID',
    w.wait_type AS '等待资源类型',
    r.wait_time AS '等待时间',
    r.wait_resource AS '等待的资源',
    w.waiting_tasks_count AS '当前正在进行等待的任务数',
    r.reads AS '物理读次数',
    r.writes AS '写次数',
    r.logical_reads AS '逻辑读次数',
    r.row_count AS '返回结果行数'
FROM sys.dm_exec_requests AS r
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) AS t
LEFT JOIN sys.dm_os_wait_stats AS w ON r.wait_type = w.wait_type
WHERE r.session_id > 50 -- 排除系统进程
ORDER BY r.cpu_time DESC;

注意:sys.dm_exec_requests仅包含当前活动的会话信息,获取过去一段时间内已经完成的慢查询,可以使用扩展事件(XEvents)来记录长时间运行的查询,并将这些信息写入一个跟踪文件,然后分析这些文件来找出历史某个时间段的慢查询。

4、SQLServer查看锁表和解锁

如果遇到数据库锁表的情况,可以通过sql语句拿到锁表进程id,然后执行杀掉进程语句,解决数据库卡死的情况。

代码语言:javascript复制
-- 第一步查询被锁表
select request_session_id   spid,OBJECT_NAME(resource_associated_entity_id) tableName   
from   sys.dm_tran_locks where resource_type='OBJECT';
--参数说明 spid   锁表进程 ;tableName   被锁表名
-- 第二步解锁语句 需要拿到spid然后杀掉缩表进程
declare @spid  int 
Set @spid  = 57 --锁表进程
declare @sql varchar(1000)
set @sql='kill ' cast(@spid  as varchar)
exec(@sql)

5、快速清理数据库日志文件

数据库日志文件随着业务系统的长期使用会非常占用存储空间,甚至占用超过几百G甚至上T,如果不需要进行一直保留数据库日志文件,可以建一个数据库作业,定时清理数据库日志文件,脚本如下:

代码语言:javascript复制
USE master
ALTER DATABASE DB SET RECOVERY SIMPLE WITH NO_WAIT
ALTER DATABASE DB SET RECOVERY SIMPLE --调整为简单模式
USE DB
DBCC SHRINKFILE (N'DB_log' , 2, TRUNCATEONLY) --设置压缩后的日志大小为2M,可以自行指定
USE master
ALTER DATABASE DB SET RECOVERY FULL WITH NO_WAIT
ALTER DATABASE DB SET RECOVERY FULL --还原为完全模式 

0 人点赞