在这种特定情况下,在MySql Structure中使用NULL的优缺点是什么?

问题描述 投票:-2回答:2

我有一个下面显示的表结构包含我所采用的角色结构:

enter image description here

让它成为“角色”表包含一些与用户角色相关的记录。现在我在这里使用了一列“is_archived(int)”,我用它来了解该角色是否仍然存在或删除。

所以我正在考虑该列的两个值:

  • “NULL”=>如果该角色仍然存在(如TRUE),
  • “1”=>如果删除/不活动(如FALSE)

对于我的表,最大记录将包含此列的“NULL”值,而默认值也为“NULL”。

现在我陷入困境,在这种情况下存在性能问题,因为我使用的是“NULL”而不是“0”。

我需要知道这种情况的优缺点(如“搜索性能”,“存储”,“索引”等)。

如果有利弊,最好的选择是什么?

mysql indexing storage
2个回答
0
投票

我同意@RickJames关于NULL。不要在你想要使用像true这样的实际值的地方使用NULL。同样,不要使用像0或''这样的实际值来表示缺少值。

至于性能影响,您应该知道要搜索NULL的存在/不存在,您将使用谓词is_archive IS [NOT] NULL

如果对查询使用EXPLAIN,您将看到该谓词计为“范围”访问类型。而搜索单个特定值,例如, is_archive = 1is_archive = 0是一种“ref”访问类型。

这将对某些查询产生性能影响。例如,如果您有(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页面格式的开销可能大于从微优化布尔存储中获得的节省。


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。)

© www.soinside.com 2019 - 2024. All rights reserved.