&引用;“不为空”;vs布尔MySQL-性能

&引用;“不为空”;vs布尔MySQL-性能,mysql,performance,Mysql,Performance,我有一列是日期时间,在转换 我计划经常打电话检查,其中converted_at不为null。因此,我正在考虑转换一个布尔字段。检查字段是否为非空与检查字段是否为假之间是否存在显著的性能差异 谢谢。如果某个领域的问题是可以回答的,那么你更倾向于将同一个问题分成两个领域。这将创建更多的基础设施,在您的情况下,这是可以避免的 至于问题的核心,我相信大多数数据库实现(包括MySQL)都会有一个内部标志,它无论如何都是布尔值,用于表示字段的可空性 你应该相信这是正确的 至于性能,更大的问题应该是分析在数据

我有一列是日期时间,
转换

我计划经常打电话检查
,其中converted_at不为null。因此,我正在考虑转换一个布尔字段
。检查字段是否为
非空
与检查字段是否为
之间是否存在显著的性能差异


谢谢。

如果某个领域的问题是可以回答的,那么你更倾向于将同一个问题分成两个领域。这将创建更多的基础设施,在您的情况下,这是可以避免的

至于问题的核心,我相信大多数数据库实现(包括MySQL)都会有一个内部标志,它无论如何都是布尔值,用于表示字段的可空性

你应该相信这是正确的


至于性能,更大的问题应该是分析在数据库上运行的典型查询,以及在何处创建适当的索引和分析表以改进执行计划,以及在查询期间使用哪些索引。这个问题将对性能产生更大的影响。

在查询性能方面,使用
WHERE converted\u at不为null
WHERE converted=FALSE
可能是相同的

但是,如果您有这个额外的位字段,它用于存储在
字段中转换的
是否为空,那么无论何时添加新行以及每次更新列,您都必须以某种方式保持完整性(通过触发器?)。所以,这是一个去规范化。也意味着更复杂的代码。此外,表上至少还有一个索引(这意味着插入/更新/删除操作要慢一点)

因此,我不认为添加这个位字段是好的


如果您可以将有问题的列从
NULL
更改为
notnull
(可能通过规范化表),您可能会获得一些性能提升(以拥有更多表为代价)。

我自己也有同样的问题。所以我决定对它进行测试。 因此,我创建了我想象的3种可能性所需的所有字段:

# option 1
ALTER TABLE mytable ADD deleted_at DATETIME NULL;
ALTER TABLE mytable ADD archived_at DATETIME NULL;

# option 2
ALTER TABLE mytable ADD deleted boolean NOT NULL DEFAULT 0;
ALTER TABLE mytable ADD archived boolean NOT NULL DEFAULT 0;

# option 3
ALTER TABLE mytable ADD invisibility TINYINT(1) UNSIGNED NOT NULL DEFAULT 0
            COMMENT '4 values possible' ;
最后是一个位字段,其中1=已存档,2=已删除,3=已删除+已存档

第一个区别是,必须为optioon 2和3创建索引

CREATE INDEX mytable_deleted_IDX USING BTREE ON mytable (deleted) ;
CREATE INDEX mytable_archived_IDX USING BTREE ON mytable (archived) ;

CREATE INDEX mytable_invisibility_IDX USING BTREE ON mytable (invisibility) ;
然后,我使用一个真实的SQL请求在主表上的13k条记录上尝试了所有选项,下面是它的外观

SELECT *
FROM mytable
LEFT JOIN  table1 ON mytable.id_qcm = table1.id_qcm
LEFT JOIN  table2 ON table2.id_class = mytable.id_class
INNER JOIN  user ON mytable.id_user = user.id_user
where mytable.id_user=1  
and mytable.deleted_at is null  and mytable.archived_at is null
# and deleted=0    
# and invisibility=0  
order BY id_mytable
或者使用上述注释的过滤器选项。
使用mysql 5.7.21-1 debian9

我的结论:

“为空”解决方案(选项1)速度稍快,或者至少性能相同

另外两个(“已删除=0”和“不可见=0”)的平均速度似乎稍慢

但是空字段选项具有决定性的优势:不需要创建索引,更容易更新,更容易查询。而且使用的存储空间更少

(additionnaly插入和更新实际上也应该更快,因为mysql不需要更新索引,但您永远不会注意到这一点)


因此,您应该使用可空数据时间字段选项。

我认为性能没有显著差异,但如果有,则可能有利于
不为空,因为在测试布尔值时,它仍然想知道它是否为空。@MichaelKrelin hacker:我猜布尔值字段将被定义为
not null
@ypercube,我认为它除了完整性约束之外不会被用作任何东西。我同意你回答的第一部分。但这并不能回答这个问题。那么你剩下的答案就跟你说的“视情况而定”一样没用了。