如何判断SQL-BIT类型占用空间的多少-Server (如何判断是否怀孕)

教程大全 2025-07-16 04:19:50 浏览

此文章主要向大家探讨的是SQL Server BIT类型占用空间的多少,对于一般的INT、CHAR、tinyint等相关的数据类型,他们所占用的存储空间都是以Byte字节为单位的,但是BIT类型由于只有0和1或者说false和true。

这种情况只需要一个Bit位就可以表示了,那么在SQL Server中BIT类型到底占用了多少空间?是不是由一个Bit位来存储的?或者可能是使用一个字节来存储的?

这两个答案都不正确!实际上BIT类型占用的空间与BIT类型的列所在表的位置有关,有些情况下BIT占用了一个字节,有些情况下BIT实际占用了几个位(几个BIT类型的列共用一个字节)。下面就来具体分析一下:

1. 单独的BIT类型的列将占用一个字节。

所谓单独就是指一个BIT类型的列的左边定长列和右边定长列都不是SQL Server BIT类型的列。例如这样一个表:

SQL Server在存储表中的数据时先是将表中的列按照原有顺序分为定长和变长(变长就是长度不固定的数据类型,如varchar,nvarchar,varbinary等)两组。在数据页中存储数据时先存储所有定长的数据,然后再存储变长的数据。这里由于c2列的左边是int类型,右边是char类型,都是定长的,而且不是BIT类型,所以c1和c3之间必须留出一个字节来存储c2,虽然c2只用到了其中的一个位。

下面我们来验证一下是否真是如我所说:

(1)插入一行数据:

(2)找到tt表数据的***页(也就是刚才插入的这行数据所在页)的文件号和页面号:

我这里返回的是0x76 00 00 00 01 00,这里需要反转过来看0x00 01 00 00 00 76。其中前两个字节是文件号,后面的是页面号,所以文件号是1,页面号是118(0x76转换成十进制就是118)

(3)使用DBCC page命令查看该页的内部结构:

这儿DBCC traceon(3604)表示将页面内容直接输出,TestDB是我创建的tt表所在的数据库,1和118前面已经说了。***一个是打印选项。0表示只输出页头;1则不会输出所有内容,只是输出有数据的内容;2表示完整的输出这个页的内容,3则和1差不多,但是要每条记录分别列出列的值。以下是输出的需要关注的内容:

关于数据行的具体格式我就不在这里多说了,在《SQL Server 2005技术内幕 存储引擎》中有详细介绍。我们插入的数据从第5个字节开始,是01000000 016161。这儿01000000就是c1,由于是int类型,所以占用4个字节。接下来01就是c2,在这里占用了1字节。再接下来6161就是c3了。

2.多个BIT类型的列之间使用变长数据类型列分开

则去掉变长列,然后看连续的SQL Server BIT类型列的个数,每列占用一个位,如果多余了8列那就再占用更多的字节。例如创建这样的表:

这里将变长列筛选出来后就变成了c1、c3、c5、c6,有3个BIT类型列是连续的,所以c1、c3、c5将公用一个字节。接下来就来验证一下:

(1)插入一条示例数据:

(2)用前面用的SQL语句,同样的方法,找出vtt表的***页为:0xC00000000100,对应的就是文件号1,页号192

(3)查看该页的内部数据:

插入的数据从第5个字节开始03ff…… 这儿03就是c1、c3、c5的数据,03转换成二进制就是00000011。c1列对应***位1,c3对应倒数第二位1,c5对应倒数第三位0。接下来的ff就是c6的值1023。后面的就是列数、NULL位图、变长列等,这里是讨论BIT位占用空间的,所以就不讲解后面这些了。

如何判断是否怀孕

3.一个表中有多个SQL Server BIT类型的列

其顺序是否连续决定了BIT位是否可以共享一个字节。SQL Server中按照列顺序存储,***列和***一列都是BIT数据类型列,不可以共用一个字节。

也就是说下面的表t1和表t2占用的空间是不同的,t1数据占用了7字节,t2数据占用了8字节。

但是在下面的t3和t4表中,由于中间是变长数据类型,所以他们的BIT列占用的数据空间是相同的。

【编辑推荐】


SQL语句大全

sp_helpdb ----------查本服务器中所有数据库 可跟库名 例:sp_helpdb 库名 ------------------------------------------------------------- sp_databases -------------查看本服务器中可用的数据库 -------------------------------------------------------------------- sp_helpfile -------------------查看当前工作着的数据库 ----------------------------------------------------------- sp_helpfilegroup ---------------查看当前工作着的组的信息。 可加参数,跟组名 例:sp_helpdb 库名 ---------------------------------------------------------------- sp_renamedb -----------改数据库名 例:sp_renamedb 旧库名,新库名 ---------------------------------------------------------------- select groupname from sysfilegroups where status=24 ---------查看文件组 =8是查只读文件组 =16是查默认文件组 =24是查即只读又默认 --------------------------------------------------------------------------- sp_dboption ----------修改数据库选项值 例:sp_dboption 库名 选项 值 值决定真假 一般用:true/faule 或off/on表示 选项一般常用为:use only(数据库拥有者)single user(单一用户)read only(只读) -------------------------------------------------------------------------- dbcc shrinkdatabase ---------收缩数据库 例:dbcc shrinkdatabase (库名,10) 收缩库,剩余空间保留10%,后面如果不加notruncate,则释放空间操作系统, 加truncateonly,归还空间给操作系统,但忽略所给的百分比数值。 ---------------------------------------------------------------------- dbcc shrinkfile ---------收缩文件 用法与ddcc shrinkdatabase相同。 ---------------------------------------------------------------------- alter where 姓名=李一 ----------把表中姓名叫李一的改为丁一。 ------------where后面跟定位的列与值 ------------------------------------------------------------------------- update 表名 set 学号=14, 姓名=陈强 where 学号=1 ------------把学号为1的同学改为学号14,姓名陈强 ----------------------------------------------------------------------- update 表名 set 学号=年龄+7, 姓名=陈一强, 年龄=29 where 学号=14 -------把学号为14的同学资料改为年龄加七赋给学号姓名改为陈一强,年龄改为29 -------如果没用where定位,则修改全部值 ------------------------------------------------------------------------ delete 表名 where 学号>30 ---------把学号大于30的资料删除 --------如不指定条件,则删表内所有数据。 这是记录日志文件的操作 ---------------------------------------------------------------- truncate table 表名 -------清空表。 不记录日志文件的操作。 -------------------------------------------------------------------- create view 图名 -------------新建视图 用法: create view 图名 as select 列名 from 表名 ------------------------------------------------------------------------------ syscomments ------------这个表存着视图代码的信息 ------------------------------------------------------------------------------ alter view 图名 with encryption as select 列名 from 表名 -----------用with encyption语句给视图原代码加密 -------------不可恢复,除非保留源代码 ------------------------------------------------------------------------------ sp_helptext 图名 -----------查看视图源代码 ----------------------------------------------------------------------------- select text from syscomments where id =(select id from sysobjects where name =图名) ---------查视图的代码 ----------------------------------------------------------------------------- create view 图名 as select * from 源图名 ------------基于源图创建新视图 ----------------------------------------------------------------------------- create view 图名 as select 列1 as 新列1,列2 新列2,列3=新列3 ---------起别名的三种方法 from 表名 -----------在新视图中为列起别名,则所见的是新起的别名 ----------------------------------------------------------------------------- sp_depends 表名 -----------查该表的相关性,有多少表、图与之相关。 ------------------------------------------------------------------------------- create view 图名 select * from 表名 where 年龄<20 with check option ---------强制插入数据符合年龄小于20的条件,加在where后面 -----------是约束insert和update语句的 ------------------------------------------------------------------------------- select 男公民.姓名,女公民.姓名 from 男公民,女公民 where 男公民.配偶编号=女公民.编号 ------------查结婚男女。 较原始的语法,后被下列语法取代 或: select 男公民.姓名,女公民.姓名 from 男公民 join 女公民 on 男公民.配偶编号=女公民.编号 -------新的形式,在join之前省略了inner语句。 --可用左连接(*=或left outer join)右连接(=*或right outer join)全连接(full outer) ----where不能做全连接,但可以做连接的约束 select * from 男公民 where 配偶编号 in (select 编号 from 女公民) --------嵌套查询,查配偶编号在女公民表中编号列中出现过的 ------------------------------------------------------------------------------- select distinct 客户表.* from (select * from 订单表 where 订单年份=2004) as d,客户表 where d.客户号=客户表.客户号 -----子查询放在from身后,也可以放在where身后 ---------------------------------------------------------------------------- select (select 子查询语句) from 表名 -------这种格式要求子查询查出的必须是唯一的数据 ---------------------------------------------------------------------------- select a.员工编号,a.员工姓名,b.员工姓名 as 领导姓名 from 员工表 as a,员工表 as b where a.部门领导编号=b.员工编号 select a.员工编号,a.员工姓名,b.员工姓名 as 领导姓名 from 员工表 as a join 员工表 as b on a.部门领导编号=b.员工编号 select a.员工编号,a.员工姓名, (select 员工姓名 from 员工表 as b where a.部门领导编号=b.员工编号) as 领导姓名 from 员工表 as a ---------三种查询员工领导的方法 ------如果里面总经理领导编号是这空的,这种查询方法不显示空值。 如要显示,则用左连接 ----------------------------------------------------------------------------- sp_tables -----------查当前数据库中的所有表 ------------------------------------------------------------------------------ select * from 男公民 union ------------联合。 自动升序排序,并去掉重复语句 select * from 女公民 -----查询结果是男公民和女公民表的总集。 如果不去掉重复的,则用 union all -----如果要降序排,则要在最后一个select语句后面加上order by 列名 desc -----用union查询时,结果集内列数必须相同,并且数据类型必须相互兼容 -----多表联合查询加order by时,后面必须跟第一个结果集的列名 ------------------------------------------------------------------------------ select top 2 成绩 from 表 order by 成绩 desc ---------查前两种最好成绩 ------------------------------------------------------------------------------- select top 2 with ties 成绩 from 表 order by 成绩 desc ---------查前两种最好成绩所有人的信息 ------------------------------------------------------------------------------- select top 1 a.成绩 from (select distinct top 3 成绩 from 表 order by 成绩 desc) as a order by 成绩 ---------嵌套查询,查考成绩第三名的值 ------------------------------------------------------------------------------- select max (SQL成绩),min (MCSE成绩) from 表 -----查SQL最高分和MCSE最低分 -----常用的函数:max(最大),min(最小),sum(总和),avg(平均值) -----count(*)统计表内数据的行数。 count(列名)统计表内列里非空值的行数 ------------------------------------------------------------------------------- select count(*) from 表名 --------查表内有多少行数据 ------------------------------------------------------------------------------- select count(列名) from 表名 ------------查表内列中有多少行非空数据 ------------------------------------------------------------------------------- select min(成绩),max(成绩),sum(成绩),avg(成绩),count(*),count(成绩) from 表名 --------返回显示数据只有一行。 中间不能加列名,如想加,可以在后面加列。 ------------------------------------------------------------------------------- group by ---------分组统计,后面跟的是列名 ---------上面select检索多少原始列,后面group by就要跟多少原始列 例: select 性别,avg(年龄) from 表名 group by 性别 -------统计性别的平均年龄 ------------------------------------------------------------------------------- select 年龄,avg(年龄) from 表名 where 年龄<23 group by 年龄 -------查年龄小于23岁的各年龄段平均年龄 -------或也可用如下方法: select 年龄,avg(年龄) from 表名 group by 年龄 having<23 -------having是统计之后的条件,where是统计之前的条件 --------having是做为group by的子句出现的,不能单独使用 ------------------------------------------------------------------------------ select 年龄,avg(年龄) from 表名 where 年龄<23 group by all 年龄 -------显示所有年龄,但只统计年龄小于23的,大于23的显示空值 ------------------------------------------------------------------------------ select 品牌,颜色,sum(价格),avg(价格) from 汽车表 group by 品牌,颜色 with cube -------多维统计,按不同品牌不同颜色统计,也是group by的子句 --------其结果出现把各品牌统计一下,最后再统计所有品牌、所有颜色的总统计 ------------------------------------------------------------------------------ select 品牌,颜色,sum(价格),avg(价格) from 汽车表 group by 品牌,颜色 with rollup ------只按第一列统计,也是group by的子句 ---------即统计品牌各颜色和所有品牌所有颜色的总统计 ------------------------------------------------------------------------------ select 品牌,颜色,价格 from 汽车表 compute sum(价格),avg(价格) ----------出现两个结果集 ------------查原始列,另外统计所有的总和与平均值 ------------------------------------------------------------------------------- select 品牌,sum(价格),avg(价格) from 汽车表 group by 品牌 ------只对汽车品牌进行统计。 进行分组的列不一定用来统计 ------------------------------------------------------------------------------ select 品牌,颜色,价格 from 汽车表 order by 品牌 compute sum(价格),avg(价格) by 品牌 --------按品牌分组统计。 分别显示品牌各款,然后再显示函数计算值 ------------------------------------------------------------------------------ exists --------存在。 相当于一个判断开关。 说对了执行,说错了放弃 用法: select * form 表名 where exists (select * from 表名 where 性别=男) ------如果存在性别为男的,执行查询。 如果不存在,则不执行命令。 ----------------------------------------------------------------------------- 数据完整性:1.实体完整性----用unique(唯一)或主键控制,数据不能重复2.值域完整性----用check控制。 控制的是列中不能有非法数据3.引用完整性----一列的取值完全依赖于前一列时,用这个。 4.用户自定义完整性 ------------------------------------------------------------------------------ create table 表名 (列1 int primary key, --------设置列级主键,紧跟在设置列的后面。 列2 int) ------------------------------------------------------------------------------- create table 表名 (列1 int, 列2 int, primary key (列1)) --------设置表级主键,放在建表语句的最后面。 ------------------------------------------------------------------------------- create table 表名 (列1 int constraint pk_表 primary key, 列2 int) --------把列1设为主键,并且起名叫:pk_表。 constraint是命名的命令

如何检查SQL Server索引填充因子

这是收藏的一些资料:SQLServer提供了一个数据库命令――DBCC SHOWCONTIG――来确定一个指定的表或索引是否有碎片。 示例:显示数据库里所有索引的碎片信息DBCC SHOWCONTIG WITH ALL_INDEXES显示指定表的所有索引的碎片信息DBCC SHOWCONTIG (authors) WITH ALL_INDEXES显示指定索引的碎片信息DBCC SHOWCONTIG (authors,aunmind)DBCC 执行结果:扫描页数:如果你知道行的近似尺寸和表或索引里的行数,那么你可以估计出索引里的页数。 看看扫描页数,如果明显比你估计的页数要高,说明存在内部碎片。 扫描扩展盘区数:用扫描页数除以8,四舍五入到下一个最高值。 该值应该和DBCC SHOWCONTIG返回的扫描扩展盘区数一致。 如果DBCC SHOWCONTIG返回的数高,说明存在外部碎片。 碎片的严重程度依赖于刚才显示的值比估计值高多少。 扩展盘区开关数:该数应该等于扫描扩展盘区数减1。 高了则说明有外部碎片。 每个扩展盘区上的平均页数:该数是扫描页数除以扫描扩展盘区数,一般是8。 小于8说明有外部碎片。 扫描密度[最佳值:实际值]:DBCC SHOWCONTIG返回最有用的一个百分比。 这是扩展盘区的最佳值和实际值的比率。 该百分比应该尽可能靠近100%。 低了则说明有外部碎片。 逻辑扫描碎片:无序页的百分比。 该百分比应该在0%到10%之间,高了则说明有外部碎片。 扩展盘区扫描碎片:无序扩展盘区在扫描索引叶级页中所占的百分比。 该百分比应该是0%,高了则说明有外部碎片。 每页上的平均可用字节数:所扫描的页上的平均可用字节数。 越高说明有内部碎片,不过在你用这个数字决定是否有内部碎片之前,应该考虑fill factor(填充因子)。 平均页密度(完整):每页上的平均可用字节数的百分比的相反数。 低的百分比说明有内部碎片。 解决碎片问题 :1.删除并重建索引 2.使用DROP_EXISTING子句重建索引 3.执行DBCC DBREINDEX 4.执行DBCC INDEXDEFRAG 删除并重建索引 :用DROP INDEX和CREATE INDEX或ALTER TABLE来删除并重建索引有些缺陷包括在删除重建期间索引会消失。 在索引删除重建时,对于查询它不在可用,查询性能也许会受到明显的影响,直到重建索引为止。 另一个潜在的缺陷是当都请求索引的时候会引起阻塞,直到重建索引为止。 通过其他的处理也能解决阻塞,就是索引被使用的时候不删除索引。 另一个主要的缺陷是在用DROP INDEX和CREATE INDEX重建聚集索引时会引起非聚集索引重建两次。 删除聚集索引时非聚集索引的行指针会指向数据堆,聚集索引重建时非聚集索引的行指针又会指回聚集索引的行位置。 删除并重建索引的确有一个好处就是通过重新排序索引页,使索引页紧凑并删除不需要的索引页来完全重建索引。 你也许需要考虑那些内部和外部碎片都很高的情况下才使用,以使那些索引回到它们应该在的位置。 使用DROP_EXISTING子句重建索引 :为了避免在重建聚集索引时表上的非聚集索引重建两次,可以使用带DROP_EXISTING子句的CREATE INDEX语句。 这个子句会保留聚集索引键值,以避免非聚集索引重建两次。 和删除并重建索引一样,该方法也可能会引起阻塞和索引消失的问题。 该方法的另一个缺陷是也强迫你去分别发现和修复表上的每一个索引。

sql2000字段类型有哪些?

(1)char、varchar、text和nchar、nvarchar、ntext char和varchar的长度都在1到8000之间,它们的区别在于char是定长字符数据,而varchar是变长字符数据。 所谓定长就是长度固定的,当输入的数据长度没有达到指定的长度时将自动以英文空格在其后面填充,使长度达到相应的长度;而变长字符数据则不会以空格填充。 text存储可变长度的非Unicode数据,最大长度为2^31-1(2,147,483,647)个字符。 后面三种数据类型和前面的相比,从名称上看只是多了个字母n,它表示存储的是Unicode数据类型的字符。 写过程序的朋友对Unicode应该很了解。 字符中,英文字符只需要一个字节存储就足够了,但汉字众多,需要两个字节存储,英文与汉字同时存在时容易造成混乱,Unicode字符集就是为了解决字符集这种不兼容的问题而产生的,它所有的字符都用两个字节表示,即英文字符也是用两个字节表示。 nchar、nvarchar的长度是在1到4000之间。 和char、varchar比较:nchar、nvarchar则最多存储4000个字符,不论是英文还是汉字;而char、varchar最多能存储8000个英文,4000个汉字。 可以看出使用nchar、nvarchar数据类型时不用担心输入的字符是英文还是汉字,较为方便,但在存储英文时数量上有些损失。 (2)datetime和smalldatetime datetime:从1753年1月1日到9999年12月31日的日期和时间数据,精确到百分之三秒。 smalldatetime:从1900年1月1日到2079年6月6日的日期和时间数据,精确到分钟。 (3)bitint、int、smallint、tinyint和bit bigint:从-2^63(-)到2^63-1()的整型数据。 int:从-2^31(-2,147,483,648)到2^31-1(2,147,483,647)的整型数据。 smallint:从-2^15(-32,768)到2^15-1(32,767)的整数数据。 tinyint:从0到255的整数数据。 bit:1或0的整数数据。 (4)decimal和numeric 这两种数据类型是等效的。 都有两个参数:p(精度)和s(小数位数)。 p指定小数点左边和右边可以存储的十进制数字的最大个数,p必须是从 1到38之间的值。 s指定小数点右边可以存储的十进制数字的最大个数,s必须是从0到p之间的值,默认小数位数是0。 (5)float和real float:从-1.79^308到1.79^308之间的浮点数字数据。 real:从-3.40^38到3.40^38之间的浮点数字数据。 在SQL Server中,real的同义词为float(24)。 数据库定义到char类型的字段时,不知道大家是否会犹豫一下,到底选char、nchar、varchar、nvarchar、text、ntext中哪一种呢?结果很可能是两种,一种是节俭人士的选择:最好是用定长的,感觉比变长能省些空间,而且处理起来会快些,无法定长只好选用定长,并且将长度设置尽可能地小;另一种是则是觉得无所谓,尽量用可变类型的,长度尽量放大些。 鉴于现在硬件像萝卜一样便宜的大好形势,纠缠这样的小问题实在是没多大意义,不过如果不弄清它,总觉得对不起劳累过度的CPU和硬盘。 下面开始了(以下说明只针对SqlServer有效): 1、当使用非unicode时慎用以下这种查询:select f from t where f = Nxx原因:无法利用到索引,因为数据库会将f先转换到unicode再和Nxx比较 2、char 和相同长度的varchar处理速度差不多(后面还有说明) 3、varchar的长度不会影响处理速度!!!(看后面解释) 4、索引中列总长度最多支持总为900字节,所以长度大于900的varchar、char和大于450的nvarchar,nchar将无法创建索引 5、text、ntext上是无法创建索引的 6、O/R Mapping中对应实体的属性类型一般是以string居多,用char[]的非常少,所以如果按mapping的合理性来说,可变长度的类型更加吻合 7、一般基础资料表中的name在实际查询中基本上全部是使用like %xx%这种方式,而这种方式是无法利用索引的,所以如果对于此种字段,索引建了也白建 8、其它一些像remark的字段则是根本不需要查询的,所以不需要索引 9、varchar的存放和string是一样原理的,即length {block}这种方式,所以varchar的长度和它实际占用空间是无关的 10、对于固定长度的字段,是需要额外空间来存放NULL标识的,所以如果一个char字段中出现非常多的NULL,那么很不幸,你的占用空间比没有NULL的大(但这个大并不是大太多,因为NULL标识是用bit存放的,可是如果你一行中只有你一个NULL需要标识,那么你就白白浪费1byte空间了,罪过罪过!),这时候,你可以使用特殊标识来存放,如:NV 11、同上,所以对于这种NULL查询,索引是无法生效的,假如你使用了NULL标识替代的话,那么恭喜你,你可以利用到索引了 12、char和varchar的比较成本是一样的,现在关键就看它们的索引查找的成本了,因为查找策略都一样,因此应该比较谁占用空间小。 在存放相同数量的字符情况下,如果数量小,那么char占用长度是小于varchar的,但如果数量稍大,则varchar完全可能小于char,而且要看实际填充数值的充实度,比如说varchar(3)和char(3),那么理论上应该是char快了,但如果是char(10)和varchar(10),充实度只有30%的情况下,理论上就应该是varchar快了。 因为varchar需要额外空间存放块长度,所以只要length(1-fillfactor)大于这个存放空间(好像是2字节),那么它就会比相同长度的char快了。 13、nvarchar比varchar要慢上一些,而且对于非unicode字符它会占用双倍的空间,那么这么一种类型推出来是为什么呢?对,就是为了国际化,对于unicode类型的数据,排序规则对它们是不起作用的,而非unicode字符在处理不同语言的数据时,必须指定排序规则才能正常工作,所以n类型就这么一点好处。 总结: 1、如果数据量非常大,又能100%确定长度且保存只是ansi字符,那么char 2、能确定长度又不一定是ansi字符或者,那么用nchar; 3、不确定长度,要查询且希望利用索引的话,用nvarchar类型吧,将它们设到400; 4、不查询的话没什么好说的,用nvarchar(4000) 5、性格豪爽的可以只用3和4,偶尔用用1,毕竟这是一种额外说明,等于告诉别人说,我一定需要长度为X位的数据

本文版权声明本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,请联系本站客服,一经查实,本站将立刻删除。

发表评论

热门推荐