在SqlServer查找表中使用tinyint而不是int是否值得?

在SqlServer查找表中使用tinyint而不是int是否值得?,sql,sql-server,database-design,Sql,Sql Server,Database Design,在SQLServer2005中设计查找表(enum)时,如果知道条目数永远不会很高,是否应该使用tinyint而不是int?我最关心的是性能,尤其是索引的效率 假设您有这些具有代表性的表格: Person ------ PersonId int (PK) PersonTypeId tinyint (FK to PersonTypes) 及 明显的因素是数据大小和编码麻烦。当person表中有1亿行时,我们使用tinyint而不是int存储了3亿字节,加上索引占用的空间。数据量不是很大,但如

在SQLServer2005中设计查找表(enum)时,如果知道条目数永远不会很高,是否应该使用tinyint而不是int?我最关心的是性能,尤其是索引的效率

假设您有这些具有代表性的表格:

Person
------
PersonId int  (PK)
PersonTypeId tinyint  (FK to PersonTypes)

明显的因素是数据大小和编码麻烦。当person表中有1亿行时,我们使用tinyint而不是int存储了3亿字节,加上索引占用的空间。数据量不是很大,但如果将设计决策应用于几十个大表,则意义重大。当然,编码的麻烦来自于ASP.NET C#/VB代码中的所有转换问题

如果我们撇开这两个问题不谈,还有什么会起作用?由于索引页的大小减小,查询是否会更加高效?或者,是否存在某种会抵消好处的填充?还有其他的问题吗

我一直只是个人使用Int,但我正在考虑tinyint在一些大型表上进行重新设计/迁移,所以我很想得到一些建议

[编辑]


在进行了这方面的实验之后,我预期的编码麻烦最终证明不是问题。从int改为tinyint根本没有导致任何铸造问题。

我怀疑使用smallint而不是int会有很多性能优势,除非是在罕见的边缘情况下。不过,您可以轻松地为此构建一个测试应用程序,创建一些测试表并执行一百万次插入/更新/选择和比较性能。

表(或索引节点项)越窄,单个IO页面上可以容纳的记录(或索引节点)越多,任何查询所需的物理(和逻辑)读取IO操作也越少。此外,单个页面上的索引节点越多,从根到叶级别的索引中的级别可能越少。如果通过缩小表的宽度,您通过了索引可以缩小一个级别的阈值,这可能会对性能产生显著影响


如果切换到TinyInt,将表的宽度从200字节改为197字节,可能不会有任何区别。。。但是如果你把它从20个字节改成14个字节(假设你有2个整数),那么它可能会很戏剧性

内存101:更小的内存意味着一次在RAM中保存更多内存,从而减少硬盘读取。如果数据库足够大,并且您正在运行某些类型的查询,那么这可能是一个非常严重的因素。但是这可能不会有太大的区别。

还有一个因素是维护索引/磁盘备份/磁带备份,这也会占用空间,但我认为最重要的是IO和内存性能

还有其他的问题吗

我不确定这是否是你所说的那种“明白了”,但我遇到过这样的情况,即使用datetime而不是smalldatetime给出了错误的函数行为,因为对于两个本来“相同”的日期,较低精度的smalldatetime与较高精度的datetime并不等同


这里不可能发生这种情况,因为tinyint/smallint/int/bigint对于同一个数字整数值都会进行相同的比较。所以在这一点上你显然是安全的,并不是说它完全回答了你的问题

除大多数情况外,任何小于int的内容都会在内存中扩展为int-如果不是,接下来的项将对齐,以浪费您应该保存的2个字节。正如我所估计的,对于我心目中的一个主表,效果将是88->70。那么可能不会有太大影响。。。不知道使用哪个db u r,但在SQL Server上,IO页是8K,因此对于表扫描/查找,您将从每页93到117条记录。。。指数呢?这些int列在索引中吗?这可能会产生比格尔效应。是的,这个表有十几个索引,并且大量用于OLTP。磁盘上的索引大小是数据大小的10倍。这些列实际上来自一个单独的表,该表正在进行非规范化以减少所需的联接数量。几乎所有索引都将被修改以包含这些新字段。然后,如果索引只有一个或两个字段,并且将它们从int(4字节)更改为TinyInt(1字节),则索引大小将减少近三倍,并且每个IO页面的索引节点数将增加近三倍
PersonTypes
-----------
PersonTypeId tinyint
PersonTypeName varchar(50)