深入理解Sqlserver文件存储之页和应用 (转)
我们每天都在使用数据库,我们部门使用最多的关系数据库有Sqlserver,Oracle,有没有想过这些数据库是怎么存放到操作系统的文件中的?有时候为了能够设计出最优的表结构,写出高性能的Sqlserver脚本,处理海量数据并发,我们必须解底层原理。由于个人兴趣最近研究了下Sqlserver的文件存储,由于水平有限,下面只讲解Sqlserver的最小存储单元-页。
什么是页,区?
什么会有一个页的概念,我们知道对于操作系统来说,文件可以认为是一个很大 的线性空间,如果按地址空间顺序分配容量(也就是按段式存储),则有可能会造成很多的外部碎片,造成很多的容量很难再次使用,只有移动合并空间才能腾出更 多的空间。例如:如下表所有,如果我现在要申请1024B字节的空间,显然下面的两个空间空间单个计算不够,合起来却是够用的的,只能移动合并空间。
8KB |
512B |
12KB |
512B |
8KB |
已分配空间 |
空闲 |
已分配空间 |
空闲 |
已分配空间 |
为了能够更好的利用磁盘空间,Sqlserver借鉴了操作系统的虚拟内存的概念,人为的将文件划分N个8KB的存储空间,这样每次分配时,都是按照8KB空间申请,就解决了外部碎片的问题,也就是说Sqlserver 中数据存储的基本单位,页的大小为8KB,每页的开头是96字节的标头用于存储有关页的存储信息,其中有页码、页类型、页的可用空间以及拥有该页对象的分配单元ID。上述的例子分配就成为下表所示:这样就解决了外部碎片问题。
业内分配 |
8kB |
12KB |
8KB |
xxKB |
|
页单元 |
8KB |
8KB |
8KB |
8KB |
空闲 |
为什么会有区的概念,已经有了页的单位难道不够吗?主要是为了更好的管理这些空间,Sqlserver将每8个页划分为一个区(如下表所示)就像百元大钞代表着100个10元人民币一样,出去买很多东西时,用百元大钞比用很多1元钱要方面。
一个分区 |
|||||||
页1 |
页2 |
页3 |
页4 |
页5 |
页6 |
页7 |
页8 |
表3
为了有个页有更具体的认识,下表为页头的结构:
图-1
行是怎么在页中存储的?
那么数据库中的数据到底是以什么样的形式存储在数据中的呢?Sqlserver是以行为单位存储的数据,也就是说表中的每条数据(每行数据为一个块)顺序存放在页中的,那么怎么找到行?也就是一行的开始地址和结束地址? Sqlserver在每页的末尾以2个字节为单位存放了每行的开始地址,这样我们就可以定位到行的开始,通过下一条的开始位置能够知道本条记录的结束位置,这样我们就可以取出这行数据了。
图-2
如图所示,如果我想取第二条数据,那么现将一页数据都读到内存中,然后从最后读取偏移为第3开始开始读取2个字节,怎么可以找到行2的开始位置,同理可以读取出行2的结束位置。
列是怎么在页中的存储?
现在我们已经读取到行了并且已经在内存里了,接下来怎么解析出一行中的所有列?也就是这些列是怎么存放的?数据库表中的列无非就两种情况:定长列、变长列。
首先假设只有定长列,那么很容易想到一样中的每列的之顺序存放就行了,因为是定长的,完全可以将每列的偏移放到另外一个地方单独存储,如果要取某个特定的列,每个列的位置很容易定位:如下表所示:
2字节 |
3字节 |
6字节 |
10字节 |
3字节 |
2字节 |
1 |
23 |
55 |
A |
C |
D |
表-4
如果要取红色的数据,那么它的
开始位置=(行开始位置)+ 2字节+3字节+6字节+10字节。
结束位置= 开始位置 + 3字节。
其中每个列的长度完全可以用另一张表存放
列 |
1 |
2 |
3 |
4 |
5 |
6 |
长度(字节) |
2 |
3 |
6 |
10 |
3 |
2 |
表-5
具体行结构的详细信息如下:
图-3
假如设计的表结构为 :
Col1 |
Col2 |
Col3 |
Col4 |
Char(5)(not null) |
Int (null) |
Char(3)(null) |
Char(6)(not null) |
表-6
在数据库中存放数据为:
Col1 |
Col2 |
Col3 |
Col4 |
‘ABCDE’ |
‘123’ |
‘null’ |
‘ccc ‘ |
表-7
则数据在数据库文件中数据以如下形式存在:
图-4
如果其中有变长列呢,这个结构又是怎么存储的?有变长列最大的不同就是每个列的长度是不定的(同一列,每行长度都不一样),也就是不能用另外一张表存放。那么我们只能把列的长度放在行内了。这样就解决了实际长度定位的问题,上面已经说过,sqlserver有一个行偏移矩阵。
如果我们定义的表结构如下:
Col1 |
Col2 |
Col3 |
Col4 |
Col5 |
Char(2)(not null) |
Varchar(250)(not null) |
Varchar(5)(null) |
Varchar(20)(not null) |
Small int (null) |
表-8
假如这行数据为:
Col1 |
Col2 |
Col3 |
Col4 |
Col5 |
‘AAA’ |
RELICATE(‘X’,250) |
null |
‘ABC’ |
123 |
表-9
则数据在数据库中实际的存放形式为:
图-5
结论:
1.数据库列中尽量不用可空类型,当值为空时,实际不占用位置,并且也不能作为索引的键值。导致where语句中含有 is null 或者 is not null 时只能进行全表扫描,并且可空类型也容易导致空引用异常。
2.在设计列时,只有列长度确定的才用定长,比如身份证。其他情况基本上应该用varchar边长类型,不但节省空间的同时,一个页存放的数据会变多。导致同样的数据量读取页的次数变少,减少I/O,提高性能。
3.如图-1所示,聚簇索引不是按物理顺序存放的,是按逻辑物理顺序存放的(大多数人在这里会有误解。)
4.正常情况下不要使用varchar(max),因为这个列的数据肯定放不在一个页里,为了解决这个问题,sqlserver在列里只存放了一个指针。真正的数据放在了其他多个页里。每读取一行中的列都会至少多一次I/O,影响性能。
附注,参考资料:
(1) Microsoft SQL Server 2005技术内幕:存储引擎(中文)
(2)微软MSDN: http://msdn.microsoft.com/zh-cn/library/ms190969(v=sql.105).aspx
深入理解Sqlserver文件存储之页和应用 (转)的更多相关文章
- Android 文件存储浅析
最近做的一个需求和文件存储有关系.由于之前没有系统梳理过,对文件存储方面的知识一直很懵懂.趁着周末有时间,赶紧梳理一波. 这首从网上找到的一张图,很好的概括了外部存储和内部存储. 下面我们再来具体介绍 ...
- Linux文件系统十问---深入理解文件存储方式(rhel6.5,EXT4)【转】
本文转载自:https://blog.csdn.net/tongyijia/article/details/52832236 前几天在红黑联盟上看了一篇博客<Linux文件系统十问—深入理解文件 ...
- Kafka深入理解-1:Kafka高效的文件存储设计
文章摘自:美团点评技术团队 Kafka文件存储机制那些事 Kafka是什么 Kafka是最初由Linkedin公司开发,是一个分布式.分区的.多副本的.多订阅者,基于zookeeper协调的分布式日 ...
- (4.19)深入理解SQLSERVER的日志链
您真的理解了SQLSERVER的日志链了吗? 转自:https://www.cnblogs.com/lyhabc/p/3460272.html 先感谢宋沄剑给本人指点迷津,还有郭忠辉童鞋今天在QQ群里 ...
- SQL Server :理解Page Free Space (PFS) 页
原文:SQL Server :理解Page Free Space (PFS) 页 我们已经讨论了GAM与SGAM页,数据页(Data Page) ,现在我们来看下页面自由空间页(Page Free S ...
- Kafka与RocketMq文件存储机制对比
一个商业化消息队列的性能好坏,其文件存储机制设计是衡量一个消息队列服务技术水平和最关键指标之一. 开头问题 kafka文件结构和rocketMQ文件结构是什么样子?特点是什么? 一.目录结构 Kafk ...
- Android_文件存储
因为项目的需求,想实现一个指导使用的欢迎页效果,通过在网上的询问,给的一种解决办法是通过SharedPreferences文件存储方式来实现,具体的实现类似于通过第一次取得SharedPreferen ...
- Android 数据存储之 文件存储
-------------------------------------------文件存储----------------------------------------------- 文件存储是 ...
- Sqlserver数据库存储路径的修改
Sqlserver数据库存储路径的修改 Sqlserver数据库存储路径问题:本系统sqlserver路径默认是存储在C盘目录下的,由于数据会慢慢变大和避免重装系统数据丢失等问题,最好手动将路径设置在 ...
随机推荐
- 【探索】利用 canvas 实现数据压缩
前言 HTTP 支持 GZip 压缩,可节省不少传输资源.但遗憾的是,只有下载才有,上传并不支持.如果上传也能压缩,那就完美了.特别适合大量文本提交的场合,比如博客园,就是很好的例子. 虽然标准不支持 ...
- angular实现统一的消息服务
后台API返回的消息怎么显示更优雅,怎么处理才更简洁?看看这个效果怎么样? 自定义指令和服务实现 自定义指令和服务实现消息自动显示在页面的顶部,3秒之后消失 1. 显示消息 这种显示消息的方式是不是有 ...
- AutoMapper:Unmapped members were found. Review the types and members below. Add a custom mapping expression, ignore, add a custom resolver, or modify the source/destination type
异常处理汇总-后端系列 http://www.cnblogs.com/dunitian/p/4523006.html 应用场景:ViewModel==>Mode映射的时候出错 AutoMappe ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(74)-微信公众平台开发-自定义菜单
系列目录 引言 1.如果不借用Senparc.Weixin SDK自定义菜单,编码起来,工作量是非常之大 2.但是借助SDK似乎一切都是简单得不要不要的 3.自定义菜单无需要建立数据库表 4.自定义菜 ...
- WPF 普通属性变化通知
问题描述:使用ObservableCollection<OrderItem> source 给Datagrid.ItemsSource赋值,在后台更新source集合后,前台Datagri ...
- enote笔记法使用范例(2)——指针(1)智能指针
要知道什么是智能指针,首先了解什么称为 “资源分配即初始化” what RAII:RAII—Resource Acquisition Is Initialization,即“资源分配即初始化” 在&l ...
- HTML5 Page Visibility
什么是 Page Visibility ? Page Visibility 即页面可见性,通过 visibilityState 的值检测页面当前是否可见.当一个网站是可见或点击选中的状态时 Page ...
- Android中Activity处理返回结果的实现方式
大家在网上购物时都有这样一个体验,在确认订单选择收货人以及地址时,会跳转页面到我们存入网站内的所有收货信息(包含收货地址,收货人)的界面供我们选择,一旦我们点击其中某一条信息,则会自动跳转到订单提交界 ...
- React Native Android gradle下载慢问题解决
很多人会遇到 初次运行 react-native run android的时候 gradle下载极慢,甚至会失败的问题 如下图 实际上这个问题好解决的 首先 把对应版本的gradle下载到本地任意一个 ...
- InnoDB:Lock & Transaction
InnoDB 是一个支持事务的Engine,要保证事务ACID,必然会用到Lock.就像在Java编程一下,要保证数据的线程安全性,必然会用到Lock.了解Lock,Transaction可以帮助sq ...