设计表的时候,对变长字段长度选择的一点思考

不管是在MSSQL还是MySQL或者Oracle,变长字段的长度衡量都是要经常面对的。
对于一个变长的字段,在满足业务的情况下(其实所谓的满足业务是一个比较模糊的东西),到底是选择varchar(50)还是varchar(200)亦或是varchar(500)?
对于保守型选择,往往是选择一个较大的长度,比如varchar(500)要比varchar(50)更具有兼容性,因为是变长字段的原因,存储空间也一样。
这样的选择并不能说就不好,看站在哪个角度来看问题。
那么,相对于varchar(50),varchar(500)在更具备兼容性的同时,有哪些不好的地方,也是需要思考的,。

这里的原则就是:对于可变长度的字段,在满足条件的前提下,尽可能使用较短的变长字段长度。

以下是一个相对极端的例子,以SQL Server为例,
TestVarchar1和TestVarchar2的SortColumn 字段长度分别是varchar(50)和varchar(8000),两个表写入10000条测一样的试数据,
SortColumn 的实际长度是36个字符。

Create Table TestVarchar1
(
    Id INT IDENTITY(1,1),
    SortColumn varchar(50)
)

Create Table TestVarchar2
(
    Id INT IDENTITY(1,1),
    SortColumn varchar(8000)
)

DECLARE @SortColumn char(36);
set @SortColumn = CAST(NEWID() as char(36))
insert into TestVarchar1(SortColumn) values (@SortColumn)
insert into TestVarchar2(SortColumn) values (@SortColumn)
GO 10000

1,基于存储空间的考虑

存储空间上,存储不超过一定长度的变长字段,不同长度的变长字段存储空间是一样的,比如选择使用varchar(50)和varchar(500)是一样的,
也就说,对于不超过50个字符串的数据存储,两者在物理空间占用上并没有区别。

这里会发现,两个表的数据在完全一致的情况下,其存储空间也是完全一样的,的确,并不会因为varchar使用一个较长的长度而多占用存储空间

2,基于性能的考虑
选择varchar(50)还是varchar(8000),在性能上确实有显著的差异,考虑到某些查询需要内存(Memory Grant),查询引擎会预估当前查询需要的内存,影响查询内存的因素有以下几个方面
1,查询的类型,有没有聚合运算,有没有排序等等
2,每个操作符涉及到的记录数量
3,数据行的大小(这里是字段类型的长度而不是字段实际长度)
当行记录的数据类型长度较大的时候,执行计划预估的平均大小较大,数据类型定义的长度越大,预估的长度越大,需要分配的内存越大
如果一个查询涉及一些聚合操作并且数据量较大,就可能需要大量的内存来完成这个查询,查询引起会分配多余实际需要的内存。

两者对数据行Size的预估是一样的(尽管是完全一样的数据)

造成的结果就是两个查询的内存授予是一样的,同时第二个执行计划还有一个警告信息(黄色的感叹号)

以上可以看出,尽管两个表的数据是完全一致的,
不过字段的最大长度不一致,造成执行计划预估出现较大的偏差,因此给予较高的内存,浪费无所谓的资源。

再看一个通过聚合函数操作两张表的例子,会增加CPU的使用。

因此对于可变长度的字段,在满足条件的前提下,尽可能使用较短的变长字段长度。

原文地址:https://www.cnblogs.com/wy123/p/9237764.html

时间: 2024-11-09 17:31:47

设计表的时候,对变长字段长度选择的一点思考的相关文章

Kafka 消息格式中的变长字段(Varints)

kafka从0.11.0版本开始所使用的消息格式版本为v2,这个版本的消息相比于v0和v1的版本而言改动很大,同时还参考了Protocol Buffer而引入了变长整型(Varints)和ZigZag编码.为了更加形象的说明问题,首先我们来了解一下变长整型. Varints是使用一个或多个字节来序列化整数的一种方法.数值越小,其所占用的字节数就越少.Varints中每个字节都有一个位于最高位的msb位(most significant bit),除了最后一个字节外其余msb位都设置为1,最后一个

【转】对于表列数据类型选择的一点思考

原文链接:http://www.cnblogs.com/CareySon/archive/2012/06/14/ChoiceOfDataTypeWhenDesignTable.html 简介 SQL Server每个表中各列的数据类型的选择通常显得很简单,但是对于具体数据类型的选择的不同对性能的影响还是略有差别.本篇文章对SQL Server表列数据类型的选择进行一些探索. 一些数据存储的基础知识 在SQL Server中,数据的存储以页为单位.八个页为一个区.一页为8K,一个区为64K,这个意

Mysql字段长度限制你真的了解吗?

一行中可以容纳多少字段长度?每个字段拥有长度又可以是多少?是否数据类型的限制长度固定不变?带着这几个问题,我们开始进行一系列研究. 一.行容纳的字段长度 众所周知,记录是以行的形式进行保存的,Mysql5.1以后,行的保存格式默认为Compact格式.行记录Compact格式为: 变长字段 NULL标志位 记录头信息 列1数据 列2数据 列3数据 ... 第一个变长字段是记录这行的总字段长度,如果行记录的字段总长小于255字节,变长字段就占一个字节(一个字节有8位,8位的二进制最多能表示到255

删除变长列字段后使用DBCC CLEANTABLE回收空间

标签:SQL Server Reclaim space 收缩表 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://lzf328.blog.51cto.com/1196996/960310 SQL Server在删除变长列或者减小变长列的长度后,表的大小不会响应自动减小,除非DBA重建索引或者reorganized索引.变长列包括varchar,nvarchar, varchar(max), nvarchar(max), varb

SQL Server数据库学习笔记-设计表时应该考虑的因素

设计数据库其实就是设计数据库中的表.到底要注意些什么才能够设计好一个数据库呢?一个宗旨,8个建议. 一个宗旨“尽量少的表,每个表中尽量少的列,合理的表结构”. 8个建议: 第一个,首先要考虑的是咱们这个数据库的主要作用是什么?至少包含哪些数据?这些数据又分别属于哪些实体对象?对象之间又存在什么样的关系?比如说新闻文章管理系统的数据库,它要存放的数据至少包括:文章分类.文章标题.发文时间.作者:而既然是管理系统,那么肯定会有人要添加.删除或修改文章,那么就延伸出管理员,有管理员了就存在账号.密码:

设计表的时候,对于自增列做逻辑主键使用的一点思考

本文出处:http://www.cnblogs.com/wy123/p/7581380.html (保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些错误进行修正或补充,无他) 关于自增列 自增列作为数据库的一个特性之一,在MSSQL和MySQL以及Oracle中都被支持.之前在网上发现一个类似的问题,是关于MySQL的:“为什么InnoDB表最好要有自增列做主键?”自增列作为一项特性,(可能)会应用到表的设计方面,不管是在那种数据库平台下.抛开具

C++内存分配及变长数组的动态分配

//------------------------------------------------------------------------------------------------ 第一部分 C++内存分配 //------------------------------------------------------------------------------------------------ 一.关于内存 1.内存分配方式 内存分配方式有三种: (1)从静态存储区域分配

SQL Server如何在变长列上存储索引

原文:SQL Server如何在变长列上存储索引 这篇文章我想谈下SQL Server如何在变长列上存储索引.首先我们创建一个包含变长列的表,在上面定义主键,即在上面定义了聚集索引,然后往里面插入80000条记录: 1 -- Create a new table 2 CREATE TABLE Customers 3 ( 4 CustomerName VARCHAR(255) NOT NULL PRIMARY KEY, 5 Filler CHAR(138) NOT NULL 6 ) 7 GO 8

MySQL5.7快速修改表中字段长度

在mysql 5.5版本时,商用环境升级,有一个表存在六千多万数据,升级时需要修改这个表其中一个varchar类型字段的长度,当时用了大概4个多小时,还没有结束,之后我们系统mysql升级到5.7版本,再一次升级模拟测试中,又修改了该表的字段长度,这次用时为7个多小时,下面是记录的时间.(进入mysql命令行,执行tee upgrade.log,之后执行的sql都会记录到该log中,当不需要记录时,执行notee) Query OK, 0 rows affected (7 hours 48 mi