百万级sql server数据库优化案例分享

news2024/10/6 8:34:58

        在我们的IT职业生涯中,能有一次百万级的数据库的优化经历是很难得的,如果你遇到了恭喜你,你的职业生涯将会更加完美,如果你遇到并解决了,那么一定足够你炫耀很多年。

        这里我将要分享一次完美的百万级数据库优化经历,希望能给在IT行业的小伙伴一点启发和帮助。本篇分三步走:1、遇到问题;2、分析问题;3、解决问题;

1、遇到问题

        我负责一个web项目,数据主表差不多500w的历史数据,最近老是听运营部门反馈系统卡顿,甚至发生过站点宕机的情况。

        这里省略一万字,经历了各种排查,最终定性为db性能问题,进入下一步。

2、分析问题

        面对上面的问题,经过了各种常规慢查询、sql跟踪查询分析、连接数查询,始终无法解决问题,后来通过各种渠道的打听,得到了以下解决方法。

        第一步,获取数据库表阻塞sql信息:

select * from (
		 SELECT   spid,
		 blocked,
		 DB_NAME(sp.dbid) AS DBName,
		 program_name,
		 waitresource,
		 lastwaittype,
		 sp.loginame,
		 sp.hostname,
		 a.[Text] AS [TextData],
		 SUBSTRING(A.text, sp.stmt_start / 2,
		 (CASE WHEN sp.stmt_end = -1 THEN DATALENGTH(A.text) ELSE sp.stmt_end
		 END - sp.stmt_start) / 2) AS [current_cmd]
		 FROM     sys.sysprocesses AS sp OUTER APPLY sys.dm_exec_sql_text (sp.sql_handle) AS A
) a join (select blocked as blocked2
			from (select * from sys.sysprocesses where blocked>0 ) a
			where not exists(select * from (select * from sys.sysprocesses where blocked>0 ) b
where a.blocked=spid)) b on a.blocked=b.blocked2

        第二步,获取当前执行所有sql信息:

SELECT  SPID = er.session_id,Status = ses.status,[Login] = ses.login_name,Host = ses.host_name,BlkBy = er.blocking_session_id,
        DBName = DB_Name(er.database_id),CommandType = er.command,SQLStatement = st.text,ObjectName = OBJECT_NAME(st.objectid),
        ElapsedMS = er.total_elapsed_time,CPUTime = er.cpu_time,IOReads = er.logical_reads + er.reads,IOWrites = er.writes,
        LastWaitType = er.last_wait_type,StartTime = er.start_time,Protocol = con.net_transport,ConnectionWrites = con.num_writes,
        ConnectionReads = con.num_reads,ClientAddress = con.client_net_address,Authentication = con.auth_scheme  
        FROM sys.dm_exec_requests er  OUTER APPLY sys.dm_exec_sql_text(er.sql_handle) st  
                                      LEFT JOIN sys.dm_exec_sessions ses  ON ses.session_id = er.session_id  
                                      LEFT JOIN sys.dm_exec_connections con  ON con.session_id = ses.session_id  
        WHERE er.session_id > 50  ORDER BY  er.blocking_session_id DESC,er.session_id

      第三步,添加自动监控程序,每隔10s查询需要监控的数据库信息,然后把表阻塞和所有执行sql情况进行入库分析。

private void Process()
        {
            //获取itom监控数据
            string strBlock = @"select * from (
                                 SELECT   spid,
                                 blocked,
                                 DB_NAME(sp.dbid) AS DBName,
                                 program_name,
                                 waitresource,
                                 lastwaittype,
                                 sp.loginame,
                                 sp.hostname,
                                 a.[Text] AS [TextData],
                                 SUBSTRING(A.text, sp.stmt_start / 2,
                                 (CASE WHEN sp.stmt_end = -1 THEN DATALENGTH(A.text) ELSE sp.stmt_end
                                 END - sp.stmt_start) / 2) AS [current_cmd]
                                 FROM     sys.sysprocesses AS sp OUTER APPLY sys.dm_exec_sql_text (sp.sql_handle) AS A
                        ) a join (select blocked as blocked2
			                        from (select * from sys.sysprocesses where blocked>0 ) a
			                        where not exists(select * from (select * from sys.sysprocesses where blocked>0 ) b
                        where a.blocked=spid)) b on a.blocked=b.blocked2";
            string strBlockInfo = @"SELECT  SPID = er.session_id,Status = ses.status,[Login] = ses.login_name,Host = ses.host_name,BlkBy = er.blocking_session_id,
                                    DBName = DB_Name(er.database_id),CommandType = er.command,SQLStatement = st.text,ObjectName = OBJECT_NAME(st.objectid),
                                    ElapsedMS = er.total_elapsed_time,CPUTime = er.cpu_time,IOReads = er.logical_reads + er.reads,IOWrites = er.writes,
                                    LastWaitType = er.last_wait_type,StartTime = er.start_time,Protocol = con.net_transport,ConnectionWrites = con.num_writes,
                                    ConnectionReads = con.num_reads,ClientAddress = con.client_net_address,Authentication = con.auth_scheme  
                                    FROM sys.dm_exec_requests er  OUTER APPLY sys.dm_exec_sql_text(er.sql_handle) st  
                                                                  LEFT JOIN sys.dm_exec_sessions ses  ON ses.session_id = er.session_id  
                                                                  LEFT JOIN sys.dm_exec_connections con  ON con.session_id = ses.session_id  
                                    WHERE er.session_id > 50  ORDER BY  er.blocking_session_id DESC,er.session_id";
            DataTable dtBlock = SqlHelper.ExecuteDataTable(connectionTTItom, CommandType.Text, strBlock);
            DataTable dtSqlInfo = SqlHelper.ExecuteDataTable(connectionTTItom, CommandType.Text, strBlockInfo);

            //数据入库
            if (dtBlock != null && dtBlock.Rows.Count > 0)
            {
                foreach (DataRow dr in dtBlock.Rows)
                {
                    try
                    {
                        Insert_BlockedInfo(dr, "itom");
                    }
                    catch (Exception ex)
                    {
                        _logger.Info("Insert_BlockedInfo方法异常,"+ex.ToString());
                    }
                    
                }
            }

            if (dtSqlInfo != null && dtSqlInfo.Rows.Count > 0)
            {
                foreach (DataRow dr in dtSqlInfo.Rows)
                {
                    try
                    {
                        Insert_SqlInfo(dr, "itom");
                    }
                    catch (Exception ex)
                    {
                        _logger.Info("Insert_SqlInfo方法异常," + ex.ToString());
                    }
                    
                }
            }
        }

3、解决问题

        有了以上的准备工作,有了所有的db执行情况数据,我们就很容易对db进行分析了。当业务反馈访问异常的时候,我们只需要打开监控数据,根据监控时间范围就能很容易得看到导致表阻塞的语句。

select top 200 * from dbo.Monitor_BlockedInfo where createtime>'xxxx' and createtime<'xxxx' order by id desc 

        除了查看当前阻塞语句,我们还可以根据当前时间点的并行sql数量来监控数据库高负载时间段,具体情况如下:

-- 先检查时间段内sql堆积数量
select convert(char(19),createtime,120),COUNT(1)
from dbo.Monitor_SqlInfo 
where createtime>'2023-07-17 08:00:00' --and createtime<'2023-06-21 08:59:00'
group by convert(char(19),createtime,120)
order by COUNT(1) desc

 

         最后,我们根据高负载时间点,查询当前时间点的所有sql执行情况,有了上面的数据,db的运行情况就被拿捏的稳稳的了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/763153.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

高效管理,轻松掌控项目进度

通过Zoho Projects以项目化的方式让企业中的一切任务井井有条&#xff0c;无论是个人事务、团队计划&#xff0c;还是跨部门协同。以下是七个步骤来实现高效的任务协作&#xff0c;使企业中的任务井井有条。 1、安排和跟进任务 通过Zoho Projects项目管理工具轻松创建任务&…

一文了解JNPF低代码开发平台

一、关于低代码 JNPF平台在提供无代码&#xff08;可视化建模&#xff09;和低代码&#xff08;高度可扩展的集成工具以支持跨功能团队协同工作&#xff09;开发工具上是独一无二的。支持简单、快速地构建及不断改进Web端应用程序&#xff0c;可为整个应用程序的生命周期提供全…

matplotlib笔记 sviewgui (鼠标拖拽绘制csv的matplotlib图)

1 先看一下效果 2 导入数据方式 2.1 select选择本地数据 import sviewgui.sview as sv sv.buildGUI()然后会跳出前面的那个GUI界面 2.2 在buildGUI的时候传入数据路径 import sviewgui.sview as sv sv.buildGUI(C:/Users/16000/tip.csv)2.3 参数是DataFrame import sview…

【三维重建】【深度学习】NeuS代码Pytorch实现--训练阶段代码解析(上)

【三维重建】【深度学习】NeuS代码Pytorch实现–训练阶段代码解析(上) 论文提出了一种新颖的神经表面重建方法&#xff0c;称为NeuS&#xff0c;用于从2D图像输入以高保真度重建对象和场景。在NeuS中建议将曲面表示为有符号距离函数(SDF)的零级集&#xff0c;并开发一种新的体绘…

使用wxPython和pillow开发拼图小游戏(一)

刚学习python&#xff0c;心血来潮&#xff0c;使用wxPython和pillow开了一个简单的拼图小游戏&#xff0c;大家分享一下 wxPython是Python语言的一套优秀的GUI图形库&#xff0c;在此项目里主要用来开发GUI客户页面&#xff1b;Pillow是一个非常好用的图像处理库&#xff0c;…

在 3ds Max 中对链模型进行摆放姿势处理

推荐&#xff1a; NSDT场景编辑器助你快速搭建可二次开发的3D应用场景 建模和“摆姿势”3D链可能看起来是一项繁琐的工作&#xff0c;但实际上可以通过使用阵列工具并将链中的链接视为骨骼来轻松完成。在本教程中&#xff0c;我将向您展示如何对链条进行建模&#xff0c;并通过…

FPGA-DFPGL22学习6-led

系列文章之 上章 FPGA-DFPGL22学习5-VERILOG 文章目录 系列文章之 上章前言一、原理图端口对应 二、程序设计三、程序编写四、仿真五、工程下载 前言 和原子哥一起学习FPGA 开发环境&#xff1a;正点原子 ATK-DFPGL22G 开发板 参考书籍&#xff1a; 《ATK-DFPGL22G之FPGA开…

linux定时删除三天前的binlog日志(docker)

docker的mysql的binlog日志目录 # docker inspect bb61c3c5a7e8shell脚本 写先一个删除的shell脚本 auto-del.sh 真正删除之前&#xff0c;先用下面的语句查下是不是要删除的文件&#xff0c;这里是删除三天前的日志 find /var/lib/docker/volumes/xxxx/_data/ -mtime 3 -n…

C++--day2(字符串、引用、函数重载、哑元)

​​​​​​​​​​​​​​​​​​​​​ ​​​​​​​

【多模态】2、NLTK | 自然语言处理工具包简介

文章目录 一、什么是 NLTK 包二、如何使用三、phrase grounding 使用 NLTK 示例 一、什么是 NLTK 包 NLTK 全称是 Natural Language Toolkit&#xff0c;自然语言处理工具包&#xff0c;是 NLP 领域中常用的 python 库 NLTK 的作用&#xff1a; 语料库文本预处理&#xff1a…

dp算法 力扣123 买卖股票的最佳时机 III

本文是Java代码编写 123. 买卖股票的最佳时机 III - 力扣&#xff08;LeetCode&#xff09; 一、题目详情 给定一个数组&#xff0c;它的第 i 个元素是一支给定的股票在第 i 天的价格。 设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。 注意&#xf…

基于R语言Meta分析与【文献计量分析、贝叶斯、机器学习等】多技术融合方法与应用

Meta分析是针对某一科研问题&#xff0c;根据明确的搜索策略、选择筛选文献标准、采用严格的评价方法&#xff0c;对来源不同的研究成果进行收集、合并及定量统计分析的方法&#xff0c;最早出现于“循证医学”&#xff0c;现已广泛应用于农林生态&#xff0c;资源环境等方面。…

【MySQL】约束(三)

&#x1f697;MySQL学习第三站~ &#x1f6a9;本文已收录至专栏&#xff1a;MySQL通关路 ❤️每章节附章节思维导图&#xff0c;文末附全文思维导图&#xff0c;感谢各位点赞收藏支持~# 一.引入 约束是作用于表中字段上的规则&#xff0c;用于限制存储在表中的数据。 使用约束可…

DuiLib基本流程解析

文章目录 1、DuiLib基本流程 1、DuiLib基本流程 duilib的基本流程如上图&#xff0c;通过解析一个xml文件&#xff0c;将文件中的内容渲染为窗口界面&#xff0c;这个解析过程由WindowImplBase类来完成。 基本框架如下&#xff1a; 首先在公共头文件中加入如下内容&#xff1a…

python与深度学习(一):ANN和手写数字识别

目录 1. 神经网络2. 线性回归3. 激活函数3.1 Sigmoid函数3.2 Relu函数3.3 Softmax函数 4. ANN(全连接网络)模型结构5. 误差函数5.1 均方差误差函数5.2 交叉熵误差函数 6. 手写数字识别实战6.1 工具说明6.2 导入相关库6.3 加载数据6.4 数据预处理6.5 数据处理6.6 构建网络模型6.…

MySQL 备份和还原

目录 一、数据备份的重要性 二、数据库备份类型 2.1 物理备份 2.2 逻辑备份 1.完全备份 2.差异备份 3.增量备份 三、常见的备份方法 3.1 物理冷备 3.2 专用备份工具 mysqldump 或 mysqlhotcopy 3.3 启用二进制日志进行增量备份 3.4 第三方工具备份 四、MySQL完全备份…

HJ53 杨辉三角的变形

描述 以上三角形的数阵&#xff0c;第一行只有一个数1&#xff0c;以下每行的每个数&#xff0c;是恰好是它上面的数、左上角数和右上角的数&#xff0c;3个数之和&#xff08;如果不存在某个数&#xff0c;认为该数就是0&#xff09;。 求第n行第一个偶数出现的位置。如果没…

v-bind复习

1.v-bind 绑定元素属性  前端讲的一系列指令&#xff0c;主要是将值插入到模板内容中。  但是&#xff0c;除了内容需要动态来决定外&#xff0c;某些属性我们也希望动态来绑定。  比如动态绑定 a 元素的 href 属性&#xff1b;  比如动态绑定 img 元素的 src 属性&am…

企业数字化转型的“有为”与“数字化”

对企业而言&#xff0c;推动数字化转型势在必行&#xff0c;但困难重重&#xff0c;需要破旧立新的战略设计&#xff0c;更需要循序渐进的策略部署。对企业而言&#xff0c;唯有坚持“有为数据、有为组织、有为决策、有为创新”的理念和目标&#xff0c;探索战略、设施、资源、…

Python对Excel不同的行分别复制不同的次数

本文介绍基于Python语言&#xff0c;读取Excel表格文件数据&#xff0c;并将其中符合我们特定要求的那一行加以复制指定的次数&#xff0c;而不符合要求的那一行则不复制&#xff1b;并将所得结果保存为新的Excel表格文件的方法。 这里需要说明&#xff0c;在我们之前的文章Pyt…