我有一个如下所示的表结构包含我所采用的角色结构:
让它成为"角色"表包含一些与用户角色相关的记录。 现在我在这里采取了一个列#34; is_archived(int)"我用它来了解该角色仍然存在或删除。
所以我正在考虑该列的两个值:
对于我的表,最大记录将包含" NULL"此列的值和默认值也是" NULL"。
现在我处于两难境地,因为我正在使用" NULL"而不是" 0"。
我需要知道这种情况的利弊(例如"搜索性能","存储","索引"等)。
如果有利弊,最好的选择是什么?
答案 0 :(得分:1)
我的观点是NULL
用于“带外”,而不是用于克服带内值。如果存在性能或空间差异,则无关紧要。
对于true / false,请使用TINYINT NOT NULL
。它只有1个字节。你可以使用ENUM('false', 'true')
;它也是1个字节。
INT
,无论后面的数字是多少,都需要4个字节。不要将INT
用于这种低基数的事情。
让NULL
表示“尚未知晓”或您还不能说“真实”或“错误”的任何其他情况。 (因为你可能总是知道它是否已'存档',NULL
在这里没有位置。
你甚至可以使用ENUM('male', 'female', 'decline_to_state', 'transgender', 'gay', 'lesbian', 'identifies_as_male', 'North_Carolina_resident', 'other')
。 (警告:这只是一个部分列表;最好设置一个表格并JOIN
。)
答案 1 :(得分:0)
我同意@RickJames关于NULL。如果您想使用像true
这样的实际值,请不要使用NULL。同样,不要使用像0或''
这样的实际值来表示没有值。
至于性能影响,您应该知道要搜索NULL的存在/不存在,您将使用谓词is_archive IS [NOT] NULL
。
如果对查询使用EXPLAIN,您将看到该谓词计为“范围”访问类型。而搜索单个特定值,例如, is_archive = 1
或is_archive = 0
是“参考”访问类型。
这会对某些查询产生性能影响。例如,如果你有一个索引(is_archived,created_on),你尝试进行如下查询:
SELECT ... FROM roles
WHERE is_archived IS NULL AND created_on = '2017-01-31'
然后索引只有一半有用。 WHERE子句无法搜索索引中的第二列。
但是如果你使用真值,那么查询就像:
SELECT ... FROM roles
WHERE is_archived = 0 AND created_on = '2017-01-31'
将在索引中使用这两列。
重新评论NULL存储:
是的,在InnoDB存储引擎中,每行内部存储一个每列1位的位域,其中位指示每列是否为NULL。这些位紧凑地存储,即一个字节包含多达8位。位域之后是一系列列值。 NULL列不存储任何值。所以是的,从技术上讲,使用NULL会减少存储空间。
但是,我建议您简化数据管理,并在false
时使用false
。不要对其中一个值使用NULL。我想如果你按照每行节省一个字节的规模来管理数据是个例外。例如,如果您要管理数百亿行。
但是规模较小,潜在的空间节省不值得为项目添加额外的复杂性。
从透视角度来看,InnoDB页面仅填充每个数据页面15/16。因此,InnoDB页面格式的开销可能比微优化布尔存储所节省的成本更高。