SQL调优SQLSERVER 数据页

news2024/11/17 7:42:56

1. 什么是数据页

一般来说,对大块资源或者数据进行高效管理都会按照一定粒度来划分的,比如说 Windows 对内存的管理就是按照 内存页 (4k) 来进行划分,言外之意就是 SQLSERVER 对 mdf 的管理也是按照 数据页 (8k) 来划分的,画个图大概就是这样的。

 那如何来验证这个结论呢?刚才也说了数据都在数据页上,我们弄点数据然后在指定的数据页上提取出来就好了

CREATE DATABASE MyTestDB
GO
USE MyTestDB;
GO
IF OBJECT_ID('person') IS NOT NULL
    DROP TABLE person;
CREATE TABLE person
(
    id INT IDENTITY,
    name CHAR(5)
);
GO
INSERT INTO dbo.person( name ) VALUES ('john');
INSERT INTO dbo.person( name ) VALUES ('mary');

2. 寻找数据所在的数据页 

刚才图中也说了 mdf 是由无数个 数据页 拼出来的,那如何找到 person 表所在的数据页呢?其实微软提供了一个 dbcc ind 命令可以帮我们洞察出来,同时记得开始 3604 标记,让输出显示在控制台上,而不是默认的错误日志中,这个命令具体怎么用,大家可以查看官方文档。 


DBCC TRACEON(3604)
DBCC IND(MyTestDB,person, -1)

 

 从输出看有两条记录,第一个是 PagePID=41 是 IAM 数据页,而PagePID=280 就是我们 person 表记录所在的数据页编号,也就是说 person 表的记录在 mdf 文件偏移为 0n280 * 0n8192 的位置,用 WinDbg 算一下就是 0x00230000


0:090> ? 0n280 * 0n8192
Evaluate expression: 2293760 = 00000000`00230000

 那是不是呢?可以用 WinHex 验证一下,为了不出现进程占用,先把 MyTestDB 下线了,最后记得再上线即可。


ALTER DATABASE MyTestDB SET OFFLINE

ALTER DATABASE MyTestDB SET ONLINE

 

 从 WinHex 上看,果然是在偏移为 0x00230000 这个数据页上。

3. 如何从内存中看到数据页

刚才我们看到的数据页只是物理硬盘上的,但数据页和数据页之间的逻辑关系肯定是在内存中用一定的数据结构来承载的,接下来看下这个 数据页 映射到 SQLSERVER 进程内存的哪里呢?微软提供了 DBCC PAGE 命令可以查看指定 数据页 的详细信息。


DBCC TRACEON(3604)
DBCC PAGE(MyTestDB,1,280,2)

输出结果如下:

DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。

PAGE: (1:280)


BUFFER:


BUF @0x000002B41104F480

bpage = 0x000002B3F0632000          bPmmpage = 0x0000000000000000       bsort_r_nextbP = 0x000002B41104F3D0
bsort_r_prevbP = 0x0000000000000000 bhash = 0x0000000000000000          bpageno = (1:280)
bpart = 1                           ckptGen = 0x0000000000000000        bDirtyRefCount = 0
bstat = 0x9                         breferences = 0                     berrcode = 0
bUse1 = 12454                       bstat2 = 0x0                        blog = 0x15ab215a
bsampleCount = 0                    bIoCount = 0                        resPoolId = 0
bcputicks = 0                       bReadMicroSec = 182                 bDirtyContext = 0x0000000000000000
bDbPageBroker = 0x0000000000000000  bdbid = 10                          bpru = 0x000002B3FA708040

PAGE HEADER:


Page @0x000002B3F0632000

m_pageId = (1:280)                  m_headerVersion = 1                 m_type = 1
m_typeFlagBits = 0x0                m_level = 0                         m_flagBits = 0x8200
m_objId (AllocUnitId.idObj) = 179   m_indexId (AllocUnitId.idInd) = 256 
Metadata: AllocUnitId = 72057594049658880                                
Metadata: PartitionId = 72057594043170816                                Metadata: IndexId = 0
Metadata: ObjectId = 581577110      m_prevPage = (0:0)                  m_nextPage = (0:0)
pminlen = 13                        m_slotCnt = 2                       m_freeCnt = 8060
m_freeData = 128                    m_reservedCnt = 0                   m_lsn = (37:584:3)
m_xactReserved = 0                  m_xdesId = (0:0)                    m_ghostRecCnt = 0
m_tornBits = -116446693             DB Frag ID = 1                      

Allocation Status

GAM (1:2) = ALLOCATED               SGAM (1:3) = NOT ALLOCATED          PFS (1:1) = 0x41 ALLOCATED  50_PCT_FULL
DIFF (1:6) = CHANGED                ML (1:7) = NOT MIN_LOGGED           

DATA:


Memory Dump @0x000000F840DF8000

000000F840DF8000:   01010000 00820001 00000000 00000d00 00000000  ....................
000000F840DF8014:   00000200 b3000000 7c1f8000 18010000 01000000  ........|...........
000000F840DF8028:   25000000 48020000 03000000 00000000 00000000  %...H...............
000000F840DF803C:   1b2a0ff9 00000000 00000000 00000000 00000000  .*..................
000000F840DF8050:   00000000 00000000 00000000 00000000 10000d00  ....................
000000F840DF8064:   01000000 6a6f686e 20020000 10000d00 02000000  ....john ...........
000000F840DF8078:   6d617279 20020000 00002121 21212121 21212121  mary .....!!!!!!!!!!
000000F840DF808C:   21212121 21212121 21212121 21212121 21212121  !!!!!!!!!!!!!!!!!!!!
000000F840DF80A0:   21212121 21212121 21212121 21212121 21212121  !!!!!!!!!!!!!!!!!!!!
...
000000F840DF9FF4:   21212121 21212121 70006000                    !!!!!!!!p.`.

OFFSET TABLE:

Row - Offset                        
1 (0x1) - 112 (0x70)                
0 (0x0) - 96 (0x60)                 


DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。

Completion time: 2022-12-30T17:48:20.5466040+08:00

从上面的 Memory Dump 区节中可以看到,数据在进程内存的 000000F840DF8064 ~ 000000F840DF8078 范围内,这里要吐槽的是内存地址按照 大端布局 的,看起来很不习惯,可以用 windbg 用 小端布局 来显示。

0:116> dp 000000F840DF8064
000000f8`40df8064  6e686f6a`00000001 000d0010`00000220
000000f8`40df8074  7972616d`00000002 21210000`00000220
000000f8`40df8084  21212121`21212121 21212121`21212121
000000f8`40df8094  21212121`21212121 21212121`21212121
000000f8`40df80a4  21212121`21212121 21212121`21212121
000000f8`40df80b4  21212121`21212121 21212121`21212121
000000f8`40df80c4  21212121`21212121 21212121`21212121
000000f8`40df80d4  21212121`21212121 21212121`21212121

 

4. sql 请求源码研究

喜欢玩 windbg 的朋友肯定想对 sqlserver 进行汇编级洞察,比如研究下 sql 请求在 sqlserver 里面的执行流是什么样的? 其实很简单,我们可以这样处理,使用 ba 对 john 的内存地址下一个硬件断点,即 ba r4 000000f840df8064+0x4 ,然后在 SSMS 上执行一条 SELECT * FROM person 语句,因为要提取 john 自然就会命中。

0:104> ba r4 000000f840df8064+0x4 
0:104> g
Breakpoint 0 hit
sqlmin!BTreeMgr::GetHPageIdWithKey+0x4a:
00007ff8`d4ea121a 48894c2478      mov     qword ptr [rsp+78h],rcx ss:000000f8`45278028=0000024800000025
0:102> k
 # Child-SP          RetAddr               Call Site
00 000000f8`45277fb0 00007ff8`d4ea0b59     sqlmin!BTreeMgr::GetHPageIdWithKey+0x4a
01 000000f8`45278450 00007ff8`d4ea08b7     sqlmin!IndexPageManager::GetPageWithKey+0x119
02 000000f8`45278d20 00007ff8`d4eb22d1     sqlmin!GetRowForKeyValue+0x203
03 000000f8`45279880 00007ff8`d4eb2a39     sqlmin!IndexDataSetSession::GetRowByKeyValue+0x141
04 000000f8`45279a70 00007ff8`d4eb279b     sqlmin!IndexDataSetSession::FetchRowByKeyValueInternal+0x230
05 000000f8`45279ed0 00007ff8`d4eb2883     sqlmin!RowsetNewSS::FetchRowByKeyValueInternal+0x437
06 000000f8`4527a000 00007ff8`d4eaadab     sqlmin!RowsetNewSS::FetchRowByKeyValue+0x96
07 000000f8`4527a050 00007ff8`d4f93d60     sqlmin!CMEDScan::StartSearch+0x4f8
08 000000f8`4527a170 00007ff8`d4f93f3a     sqlmin!CMEDCatYukonObject::GetTemporalCurrentTableId+0x10e
09 000000f8`4527a380 00007ff8`d801f0d1     sqlmin!CMEDProxyRelation::GetTemporalCurrentTableId+0x7a
0a 000000f8`4527a3c0 00007ff8`d801dfb8     sqllang!CAlgTableMetadata::FPartialBind+0xb58
0b 000000f8`4527a580 00007ff8`d80394b3     sqllang!CAlgTableMetadata::Bind+0x317
0c 000000f8`4527a620 00007ff8`d800415d     sqllang!CRelOp_Get::BindTree+0x78f
0d 000000f8`4527a890 00007ff8`d80418a1     sqllang!COptExpr::BindTree+0x85
0e 000000f8`4527a8c0 00007ff8`d800415d     sqllang!CRelOp_FromList::BindTree+0x31
0f 000000f8`4527a920 00007ff8`d802c2a3     sqllang!COptExpr::BindTree+0x85
10 000000f8`4527a950 00007ff8`d800415d     sqllang!CRelOp_QuerySpec::BindTree+0x2e8
11 000000f8`4527aa60 00007ff8`d80042dd     sqllang!COptExpr::BindTree+0x85
12 000000f8`4527aa90 00007ff8`d800415d     sqllang!CRelOp_SelectQuery::BindTree+0x489
13 000000f8`4527ab80 00007ff8`d8003f23     sqllang!COptExpr::BindTree+0x85
14 000000f8`4527abb0 00007ff8`d8004e47     sqllang!CRelOp_Query::FAlgebrizeQuery+0x4bd
15 000000f8`4527ae30 00007ff8`d7ff5576     sqllang!CProchdr::FNormQuery+0x8f
16 000000f8`4527ae70 00007ff8`d7ff4a79     sqllang!CProchdr::FNormalizeStep+0x5bd
17 000000f8`4527b4b0 00007ff8`d7ff5124     sqllang!CSQLSource::FCompile+0xea5
18 000000f8`4527e1b0 00007ff8`d7e659c3     sqllang!CSQLSource::FCompWrapper+0xcb
19 000000f8`4527e280 00007ff8`d7e6387a     sqllang!CSQLSource::Transform+0x721
1a 000000f8`4527e3e0 00007ff8`d7e6e67b     sqllang!CSQLSource::Execute+0x4fa
1b 000000f8`4527e8c0 00007ff8`d7e6d815     sqllang!process_request+0xca6
1c 000000f8`4527efc0 00007ff8`d7e6d5ef     sqllang!process_commands_internal+0x4b7
1d 000000f8`4527f0f0 00007ff8`d4096523     sqllang!process_messages+0x1d6
1e 000000f8`4527f2d0 00007ff8`d4096e6d     sqldk!SOS_Task::Param::Execute+0x232
1f 000000f8`4527f8d0 00007ff8`d4096c75     sqldk!SOS_Scheduler::RunTask+0xa5
20 000000f8`4527f940 00007ff8`d40bb160     sqldk!SOS_Scheduler::ProcessTasks+0x39d
21 000000f8`4527fa60 00007ff8`d40baa5b     sqldk!SchedulerManager::WorkerEntryPoint+0x2a1
22 000000f8`4527fb30 00007ff8`d40bafa4     sqldk!SystemThreadDispatcher::ProcessWorker+0x3ed
23 000000f8`4527fe30 00007ff8`f6d86fd4     sqldk!SchedulerManager::ThreadEntryPoint+0x3b5
24 000000f8`4527ff20 00007ff8`f865cec1     KERNEL32!BaseThreadInitThunk+0x14
25 000000f8`4527ff50 00000000`00000000     ntdll!RtlUserThreadStart+0x21

从线程栈上看,有 SQLSERVER 核心的 Scheduler ,Task 以及 命令分析器,查询优化器,查询执行器 等各种核心元素

深入的理解数据,索引在数据页上的布局,可以从根本上帮助我们理解如何减少请求在数据页上的流转,减少逻辑读,从而提升 sql 的查询性能。 

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

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

相关文章

(小记)matlab散点图

Matlab散点图两种画法一、plot画散点图二、scatter画散点图三、matlab工具画散点图plot画我可以设置坐标轴之类的,方便论文使用;scatter没设置成功。一、plot画散点图 参考:matlab中二维散点图,MATLAB实例:二维散点图 自用代码 …

一站式迁移,人大金仓助力保险业务无感升级

2021年3月,国家发布《中华人民共和国国民经济和社会发展第十四个五年规划和2035年远景目标纲要》,纲要明确提出“稳妥发展金融科技,加快金融机构数字化转型”、“推进金融业信息化核心技术安全可控,维护金融基础设施安全”。2022年…

如果通过股价均线分析股票

目录如果通过股价均线分析股票获取数据为什么要计算均价计算均价分析结果如果通过股价均线分析股票 获取数据 股票数据获取渠道非常丰富,可以通过上一篇文章 各大股票开放接口介绍中接口获取数据,需要提供技术支持的可以私聊。 为什么要计算均价 股票…

MongoDB:基础概述

MongoDB 是一个开源的、跨平台的、面向文档的、基于分布式文件存储的数据库系统,MongoDB 是由 C 语言开发,旨在为 Web 应用提供可扩展的高性能数据存储解决方案。在高负载的情况下,通过添加更多的节点,可以保证服务器性能。 本篇内…

【技术分享】无纸化会议|智慧教室同屏走RTSP组播还是RTMP?

技术背景 我们在做内网多人同屏(比如无纸化会议、智慧教室同屏)技术方案的时候,遇到个问题:到底使用轻量级RTSP服务实现组播,还是基于RTMP的解决方案? 先说为什么大家喜欢组播吧: 组播技术方…

js实现复制粘贴剪切功能

文章目录js实现复制粘贴功能方式一:原生方式实现复制粘贴剪切(不推荐)方式二:浏览器自带clipboard API实现复制粘贴(推荐)简介特点clipboard对象及相关APIClipboard.readText()Clipboard.read()Clipboard.w…

二叉树之红黑树

红黑树的起源 二分查找具有Ologn的时间复杂度,使用二分查找的基础是数据有序。很明显数组可以完成这一条件,但是数组也有缺点,扩容,增加,删除非常不方便。而链表则没有这些缺点,但是链表却不满足随机存取&…

第二十七讲:神州路由器PPP CHAP认证的配置

实验拓扑图如下所示 操作步骤: 步骤1:连接网络拓扑图。 步骤2:RouterA基本配置。 Router>enable !进入特权模式 Router#config !进入全局配置模式 …

React jsx 简介与一些语法规则

什么是 Jsx 简单例子&#xff1a; //create virtual dom , single quotes is not needconst VDOM <h1> Hello, React </h1> //appy virtual dom to pageReactDOM.render(VDOM, document.getElementById("test")) //first parameter is virtual dom, …

2022,我们追逐群星,也在追逐AIGC的无尽可能

2022年&#xff0c;是中国人追逐群星的里程碑之年。今年10月31日&#xff0c;中国天宫空间站的第二个科学实验模块——梦天实验舱&#xff0c;搭载长征五号B遥四运载火箭发射升空。随着之后天实验舱成功与之前发射的天和核心舱完成精准对接&#xff0c;中国空间站历史性地完成了…

使用支付宝沙盒 nodejs

1、 进入官网 https://auth.alipay.com/login/index.html 登录 2、下载秘钥转换工具 https://render.alipay.com/p/f/fd-jwq8nu2a/pages/home/index.html 3、生成密钥 注意&#xff0c;此时得到的应用私钥的格式是不对的&#xff0c;应用格式转换转换格式 4、通过3中的应用公钥…

并发编程——2.Java 线程

目录2.Java 线程2.1.创建和运行线程2.1.1.方法一&#xff1a;直接使用 Thread 类2.1.2.方法二&#xff1a;使用 Runnable 接口配合 Thread2.1.3.方法三&#xff1a;使用 FutureTask 配合 Thread2.2.观察多个线程同时运行2.3.查看进程线程的方法2.4.原理之线程运行2.5.线程的常见…

React学习06-React Router 6

React Router 6 概述 React Router 以三个不同的包发布到 npm 上&#xff0c;它们分别为&#xff1a; react-router: 路由的核心库&#xff0c;提供了很多的&#xff1a;组件、钩子。react-router-dom: 包含react-router所有内容&#xff0c;并添加一些专门用于 DOM 的组件&…

Elasticsearch处理表关联关系的N种方式

Elasticsearch处理表关联关系是比较复杂的问题&#xff0c;处理不好会出现性能问题、数据一致性问题等&#xff1b; 今天我们特意分享一下几种方式&#xff0c;对象类型&#xff08;宽表&#xff09;、嵌套类型、父子关联关系、应用端关联&#xff0c;每种方式都有特定的业务需…

CycloneDDS(3)安全Security

本规范定义了符合DDS实现的安全模型和服务插件接口(SPI)架构。DDS安全模型通过DDS实现调用这些SPI来实现。 构成DDS安全模型的三个插件是: 1、身份验证服务插件 提供验证调用DDS操作的应用程序和/或用户身份的方法。包括在参与者之间执行相互身份验证和建立共享秘密的设施…

深度学习模型训练的tricks总结

学习率角度 学习率是一个非常非常重要的超参数&#xff0c;这个参数呢&#xff0c;面对不同规模、不同batch-size、不同优化方式、不同数据集&#xff0c;其最合适的值都是不确定的&#xff0c;我们无法光凭经验来准确地确定lr的值&#xff0c;我们唯一可以做的&#xff0c;就…

从零开始配置vim(30)——DAP的其他配置

很抱歉这么久才来更新这一系列&#xff0c;主要是来新公司还在试用期&#xff0c;我希望在试用期干出点事来&#xff0c;所以摸鱼的时间就少了。加上前面自己阳了休息了一段时间。在想起来更新就过去一个多月了。废话不多说了&#xff0c;让我们开始进入正题。 在前一章&#…

JUC 并发进阶学习(一)

该学习笔记是本人依据相关的学习视频整体汇总&#xff0c;相关的视频学习可以自己去搜看看。 【狂神说Java】JUC并发编程最新版通俗易懂_哔哩哔哩_bilibili 一、什么是JUC 从中就可以看出JUC&#xff0c;实质就是三个包&#xff0c;后面晖详细说明三个包下各个类功能。 java.…

程序员的测试课

git项目地址&#xff1a;GitHub - dreamhead/geektime-todo: Geektime Todo is a demo todo project for Geektime column. 1、实现一个Todo应用 设计规范 1、对于输入参数的检测&#xff0c;由入口部分代码进行处理。如空字符串。 2、Repository 的问题以运行时异常 的形式抛…

Django+Celery+Flower实现异步和定时任务及其监控告警

用Django框架进行web开发非常的快捷方便&#xff0c;但Django框架请求/响应是同步的。但我们在实际项目中经常会碰到一些耗时的不能立即返回请求结果任务如&#xff1a;数据爬取、发邮件等&#xff0c;如果常时间等待对用户体验不是很好&#xff0c;在这种情况下就需要实现异步…