一个字节引发的存储空间问题

本文通过对比两个仅差一个字节的表在SQL Server中的存储情况,揭示了合理选择数据类型的重要性。当表中的一行数据接近一页的存储容量时,即使细微的字段差异也会显著影响整体存储效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

来自:http://blog.youkuaiyun.com/herowang/article/details/4436605

/***************************************************

          作者:herowang(让你望见影子的墙)

    日期:2009.11.4

          注:    转载请保留此信息

    更多内容,请访问我的博客:blog.youkuaiyun.com/herowang

****************************************************/

一个字节引发的存储空间问题

今天在偶然看到了一篇文章,忽然想起疯子的一个帖子中,一直没有想明白的问题,可能和这个有关系,验证了一下,果然如此。

一、起因:

-- 创建2个测试表

CREATE TABLE [dbo].[Table_2019]([Data] [nchar](2019) NOT NULL)

CREATE TABLE [dbo].[Table_2020]([Data] [nchar](2020) NOT NULL)

go

-- 填充数据

declare @i int

set @i = 0

while(@i < 20)

begin

    insert Table_2019(Data) values('')

    insert Table_2020(Data) values('')

    select @i = @i + 1

end

go

查看每个表所占用的空间,结果:

Table_2020 表数据占了 160kb ,Table_2019 表数据占了 80 kb

二、问题

两张表中的字符长度相差为1,(因为数据类型为nchar,所以数据所占用的空间实际相差为2),但是两张表所占用的空间确相差一倍,原因何在?

三、分析

要解释这个问题,首先先要搞清楚sql server中表的存储结构:

那么在表中存储一行数据,除了本身的数据之外,至少还需要1+1+2+2+1=7个字节。

所以对于Table_2019来说,需要7+2019*2=4045个字节的空间,

    对于Table_2020来说,需要7+2020*2=4047个字节的空间。

对于数据库的一页而言(最小的存储单位),一页的空间为8K(8192B)。一个数据页是由3部分组成:页头、数据行和行偏移矩阵,页头保存了页的编号、上一页ID、下一页ID、可以字节数等等关于该页的基本信息。页头的大小是固定的96个字节,所以剩下8192-96=8096个字节用于存储数据行和行偏移矩阵。

行偏移矩阵在页的最后面,而且是倒序排列的,使用2个字节来表示数据行在页面内部的偏移量,有1行数据则行偏移矩阵的大小是2字节,有2行数据则行偏移矩阵的大小是4字节,以此类推。

下面我们再来分析下这两张表:

1、table_2019:存储数据需要的空间为4045B,加上也最后面的行偏移,为4047B,而一个数据库页剩余的空间为8096B,这样的话,一个数据能够存储两行的数据。8096>4047*2=8094

2、table_2020:存储数据需要的空间为4047B,加上也最后面的行偏移,为4049B,而一个数据库页剩余的空间为8096B,这样的话,一个数据只能够存储一行的数据。8096<4049*2=8098。

     这样,我们就会发现,同样的数据,对于table_2020所需要的存储空间是table_2019的二倍。

四、建议

    从上面就可以发现,在对表的设计过程当中,为某一列选择适当的数据类型是非常重要的。尤其是对字符类型,长度的设置一定要合适,尽量让一页能够存储更多行的数据,来减少I/O,提高数据库的效率。

 

<think>嗯,用户的问题是关于PCIe配置空间中BAR的定义和功能。从对话历史看,用户之前已经了解过BAR与设备寄存器的映射关系,现在更聚焦在配置空间这个特定场景下的BAR定义。用户引用了三篇资料,其中[1]明确区分了配置空间和BAR空间的概念,[2]提到BAR配置过程,[3]则说明配置空间的结构。 用户可能正在学习PCIe驱动开发,需要理解硬件层面的寄存器设计。ta连续追问BAR相关机制,说明在实践或学习中遇到了具体问题,比如调试设备时发现寄存器访问异常。深层需求可能是想建立从硬件规范到软件实现的完整认知链条。 需要重点解析三个维度:第一是BAR在配置空间中的物理位置(标准头的0x10-0x24偏移),第二是BAR的双重功能(空间类型声明+地址存储),第三要关联之前的地址转换知识。特别要强调BAR值在设备枚举前后的变化——初始状态是设备要求的空间属性,写入后才是实际基地址。 用户引用的材料[1]中"BAR空间通过配置空间管理"的表述容易引发概念混淆,需明确:配置空间是256字节的硬件寄存器组,BAR只是其中6个寄存器,而BAR空间指的是BAR寄存器指向的设备地址区域。这个关键区分点要在回复中用表格对比呈现。 考虑到用户技术背景,可以适当引入Linux源码中的pci_read_config_dword()这类实际接口,但避免展开过多代码细节。最后生成的问题要覆盖配置空间访问方法这种实操性内容,因为用户引用的[3]提到过但未深入。</think>### PCIe配置空间中BAR寄存器详解 #### 一、BAR的定义 BAR(Base Address Register)是**PCIe配置空间中的专用寄存器组**,位于配置空间标准头的0x10-0x24偏移位置[^3]。每个设备最多有6个BAR寄存器(BAR0-BAR5),其核心功能是: 1. **声明设备需求**:向系统申明所需地址空间类型和大小 2. **存储基地址**:接收系统分配的物理地址基值 3. **建立映射桥梁**:连接CPU地址空间与设备寄存器 #### 二、BAR的功能解析 | 功能阶段 | 机制 | 作用 | |---------|------|------| | **初始化阶段** | 系统读取BAR值 | 获取设备资源需求<br>• Bit 0=0: MMIO空间<br>• Bit 0=1: I/O空间<br>• 低位掩码计算空间大小[^2] | | **地址分配** | 系统写入基地址 | 分配唯一物理地址<br>• 32位设备:BAR存储完整基址<br>• 64位设备:BAR0+1联合存储[^1] | | **运行时访问** | CPU通过基址+偏移访问 | 实现寄存器操作<br>• 控制寄存器:基址+0x00<br>• 状态寄存器:基址+0x04 | #### 三、BAR寄存器结构 ```markdown | 比特位 | 31-4 | 3 | 2-1 | 0 | |--------|--------------|--------|--------|-------| | 功能 | 基地址字段 | Prefetch | 类型 | 空间标识 | | 说明 | 实际地址高28位| 预取使能 | 00=32位 | 0=MMIO | | | | | 10=64位 | 1=I/O | ``` *示例:BAR值 `0xFFFF0001` 表示请求32位I/O空间,掩码计算得空间大小为64KB* #### 四、BAR与其他空间的关系 ```mermaid graph LR A[PCIe配置空间] --> B[标准头区域] B --> C[BAR寄存器组] C --> D[映射设备寄存器空间] D --> E[设备控制寄存器] D --> F[设备状态寄存器] D --> G[设备数据缓冲区] ``` - **配置空间**:256字节/4KB的硬件寄存器组(包含BAR)[^3] - **BAR空间**:BAR指向的设备寄存器区域(独立于配置空间)[^1] #### 五、关键特性 1. **动态重定位** 系统重启时重新分配基地址,支持热插拔设备[^2] 2. **空间隔离** 每个设备的BAR空间独立,避免地址冲突[^1] 3. **DMA基础** 设备通过BAR获取主机内存地址实现高效传输 *示例:NVMe控制器通过BAR0获取PRP列表地址[^1]* 4. **访问控制** OS通过设置BAR范围限制设备访问权限 > 典型应用:显卡通过BAR1映射显存空间,CPU通过`BAR1基址+偏移量`访问显存数据[^1] --- ### 相关问题 1. PCIe设备枚举过程中如何通过BAR判断设备所需资源类型? 2. Linux内核中`pci_read_config_dword()`如何读取BAR寄存器的原始值? 3. 为什么64位地址空间的设备需要占用两个连续的BAR寄存器? 4. 在设备驱动开发中如何通过BAR值计算设备寄存器空间大小? 5. PCIe配置空间中的扩展能力寄存器(ECAP)与BAR有何关联?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值