我们每天都在使用数据库,我们部门使用最多的关系数据库有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文件存储之页和应用 (转)的更多相关文章

  1. Android 文件存储浅析

    最近做的一个需求和文件存储有关系.由于之前没有系统梳理过,对文件存储方面的知识一直很懵懂.趁着周末有时间,赶紧梳理一波. 这首从网上找到的一张图,很好的概括了外部存储和内部存储. 下面我们再来具体介绍 ...

  2. Linux文件系统十问---深入理解文件存储方式(rhel6.5,EXT4)【转】

    本文转载自:https://blog.csdn.net/tongyijia/article/details/52832236 前几天在红黑联盟上看了一篇博客<Linux文件系统十问—深入理解文件 ...

  3. Kafka深入理解-1:Kafka高效的文件存储设计

    文章摘自:美团点评技术团队  Kafka文件存储机制那些事 Kafka是什么 Kafka是最初由Linkedin公司开发,是一个分布式.分区的.多副本的.多订阅者,基于zookeeper协调的分布式日 ...

  4. (4.19)深入理解SQLSERVER的日志链

    您真的理解了SQLSERVER的日志链了吗? 转自:https://www.cnblogs.com/lyhabc/p/3460272.html 先感谢宋沄剑给本人指点迷津,还有郭忠辉童鞋今天在QQ群里 ...

  5. SQL Server :理解Page Free Space (PFS) 页

    原文:SQL Server :理解Page Free Space (PFS) 页 我们已经讨论了GAM与SGAM页,数据页(Data Page) ,现在我们来看下页面自由空间页(Page Free S ...

  6. Kafka与RocketMq文件存储机制对比

    一个商业化消息队列的性能好坏,其文件存储机制设计是衡量一个消息队列服务技术水平和最关键指标之一. 开头问题 kafka文件结构和rocketMQ文件结构是什么样子?特点是什么? 一.目录结构 Kafk ...

  7. Android_文件存储

    因为项目的需求,想实现一个指导使用的欢迎页效果,通过在网上的询问,给的一种解决办法是通过SharedPreferences文件存储方式来实现,具体的实现类似于通过第一次取得SharedPreferen ...

  8. Android 数据存储之 文件存储

    -------------------------------------------文件存储----------------------------------------------- 文件存储是 ...

  9. Sqlserver数据库存储路径的修改

    Sqlserver数据库存储路径的修改 Sqlserver数据库存储路径问题:本系统sqlserver路径默认是存储在C盘目录下的,由于数据会慢慢变大和避免重装系统数据丢失等问题,最好手动将路径设置在 ...

随机推荐

  1. nodejs进阶(2)—函数模块调用

    函数调用 1. 文件内普通函数调用 创建一个js文件命名为2_callFunction.js,其中定义一个函数fun1,向返回对象输出了一段字符串“你好,我是fun1”. //------------ ...

  2. .NET平台开源项目速览(17)FluentConsole让你的控制台酷起来

    从该系列的第一篇文章 .NET平台开源项目速览(1)SharpConfig配置文件读写组件 开始,不知不觉已经到第17篇了.每一次我们都是介绍一个小巧甚至微不足道的.NET平台的开源软件,或者学习,或 ...

  3. 【原创分享·微信支付】 C# MVC 微信支付教程系列之公众号支付

    微信支付教程系列之公众号支付         今天,我们接着讲微信支付的系列教程,前面,我们讲了这个微信红包和扫码支付.现在,我们讲讲这个公众号支付.公众号支付的应用环境常见的用户通过公众号,然后再通 ...

  4. CRL快速开发框架系列教程五(使用缓存)

    本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...

  5. 【NLP】Python NLTK处理原始文本

    Python NLTK 处理原始文本 作者:白宁超 2016年11月8日22:45:44 摘要:NLTK是由宾夕法尼亚大学计算机和信息科学使用python语言实现的一种自然语言工具包,其收集的大量公开 ...

  6. Javascript实现HashTable类

    散列算法可以尽快在数据结构中找出指定的一个值,因为可以通过Hash算法求出值的所在位置,存储和插入的时候都按照Hash算法放到指定位置. <script> function HashTab ...

  7. VB.NET设置控件和窗体的显示级别

    前言:在用VB.NET开发射频检测系统ADS时,当激活已存在的目标MDI子窗体时,被其他子窗体遮住了,导致目标MDI子窗体不能显示. 这个问题怎么解决呢?网上看到一篇帖子VB.NET设置控件和窗体的显 ...

  8. bzoj3208--记忆化搜索

    题目大意: 花花山峰峦起伏,峰顶常年被雪,Memphis打算帮花花山风景区的人员开发一个滑雪项目.    我们可以把风景区看作一个n*n的地图,每个点有它的初始高度,滑雪只能从高处往低处滑[严格大于] ...

  9. Java 程序优化 (读书笔记)

    --From : JAVA程序性能优化 (葛一鸣,清华大学出版社,2012/10第一版) 1. java性能调优概述 1.1 性能概述 程序性能: 执行速度,内存分配,启动时间, 负载承受能力. 性能 ...

  10. jQuery个性化图片轮播效果

    jQuery个性化图片轮播效果 购物产品展示:图片轮播器<效果如下所示> 思路说明: 每隔一段时间,实现图片的自动切换及选项卡选中效果,鼠标划入图片动画停止,划出或离开动画开始 两个区域: ...