MySQL:Enum与带索引的Varchar
假设我需要创建一个表,其中一列的值来自这个有限且永不更改的集合: “全部”、“本地”、“qa”、“暂存”和“生产” 在这种情况下使用MySQL:Enum与带索引的Varchar,mysql,database,indexing,database-design,sqldatatypes,Mysql,Database,Indexing,Database Design,Sqldatatypes,假设我需要创建一个表,其中一列的值来自这个有限且永不更改的集合: “全部”、“本地”、“qa”、“暂存”和“生产” 在这种情况下使用enum数据类型看起来是一个合适的解决方案,但在阅读了internet上的一些其他线程后,我觉得不鼓励使用它。因此,如果我想创建一个查找表并且保持evn和name的组合的唯一性也是一个要求,那么在ENUM类型的列和VARCHAR类型但在其上创建索引的列之间,我的最佳选择是什么 还考虑到此表中的插入很少,我们希望此特定查询执行得更快: SELECT `enabled`
enum
数据类型看起来是一个合适的解决方案,但在阅读了internet上的一些其他线程后,我觉得不鼓励使用它。因此,如果我想创建一个查找表并且保持evn
和name
的组合的唯一性也是一个要求,那么在ENUM类型的列和VARCHAR类型但在其上创建索引的列之间,我的最佳选择是什么
还考虑到此表中的插入很少,我们希望此特定查询执行得更快:
SELECT `enabled` FROM `features`
WHERE `name` = 'some_featuere'
AND `env` IN('all', 'qa')
ORDER BY `enabled` ASC limit 1;
哪一种设计更好?为什么
CREATE TABLE `features` (
`id` INTEGER NOT NULL AUTO_INCREMENT,
`name` VARCHAR (50) NOT NULL,
`env` ENUM('all', 'local', 'qa', 'staging', 'production') NOT NULL,
`enabled` TINYINT(1) DEFAULT 0,
`created_at` DATETIME,
`updated_at` DATETIME,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_unq_features_name_env` (`name`,`env`)
);
或
对您的问题的简短回答是“两者都不是”,因为在这两种情况下,您的查询都会使用name/env上的索引。然而,如果我必须解决一个问题,我会选择VARCHAR而不是ENUM作为两个缺点中的较小者,但我认为您的方法可能存在一些其他问题 首先,VARCHAR选项只会重复那篇文章中提到的ENUM的一个问题(即添加属性或相关数据),同时可能会失去从ENUM获得的唯一优势,即数据完整性。您可以通过查找获得数据完整性,而不必使用枚举 其次,您可能会关注查询中不存在的性能问题。它多久运行一次?有多慢?目前,您在
NAME
/ENV
上有一个索引,我想不出加快查询速度的唯一方法是使用一个覆盖索引来包含ENABLED
,但我怀疑它是一个性能杀手,我怀疑您在加入查找表时看到的差别很小
第三,“全部”作为选项没有什么意义,除非一个特性一次只能部署在一个环境中,或者同时部署在所有环境中。如果这不是真的,那么无论何时您想要应用“all”选项,都必须删除与功能名称相关的所有其他记录“全部”还将防止在不同环境中选择性地启用/禁用功能,或单独记录创建/更新事件。这就引入了不需要存在的数据管理问题
第四,虽然列
ID
、NAME
、CREATED\u AT
、UPDATED\u AT
都是与特征直接相关的属性。列ENV
和ENABLED
与该功能的部署位置和方式有关。乍一看,这建议将这些数据存储在一个完全独立的表中(可能在处创建并在
处更新以指示它们首次部署和最后更新的时间)。我个人认为Feature、Environment和Feature_Environment是单独的表,带有从Feature_Environment到其他两个的外键。您的问题的简短答案是“两者都不是”,因为您的查询在这两种情况下都会使用name/env上的索引。然而,如果我必须解决一个问题,我会选择VARCHAR而不是ENUM作为两个缺点中的较小者,但我认为您的方法可能存在一些其他问题
首先,VARCHAR选项只会重复那篇文章中提到的ENUM的一个问题(即添加属性或相关数据),同时可能会失去从ENUM获得的唯一优势,即数据完整性。您可以通过查找获得数据完整性,而不必使用枚举
其次,您可能会关注查询中不存在的性能问题。它多久运行一次?有多慢?目前,您在NAME
/ENV
上有一个索引,我想不出加快查询速度的唯一方法是使用一个覆盖索引来包含ENABLED
,但我怀疑它是一个性能杀手,我怀疑您在加入查找表时看到的差别很小
第三,“全部”作为选项没有什么意义,除非一个特性一次只能部署在一个环境中,或者同时部署在所有环境中。如果这不是真的,那么无论何时您想要应用“all”选项,都必须删除与功能名称相关的所有其他记录“全部”还将防止在不同环境中选择性地启用/禁用功能,或单独记录创建/更新事件。这就引入了不需要存在的数据管理问题
第四,虽然列ID
、NAME
、CREATED\u AT
、UPDATED\u AT
都是与特征直接相关的属性。列ENV
和ENABLED
与该功能的部署位置和方式有关。乍一看,这建议将这些数据存储在一个完全独立的表中(可能在
处创建并在
处更新以指示它们首次部署和最后更新的时间)。我个人认为Feature、Environment和Feature_Environment是单独的表,外键从Feature_Environment到其他两个表。支持枚举和反对枚举的派系之间正在进行一场“宗教”战争。你读过一篇“反”的文章。但是那篇文章中的许多“邪恶”可能不适用于你的情况
如果删除当前主键id
,并将其替换为
PRIMARY KEY(name, env)
之后,不需要二级索引
您所拥有的内容需要在一个辅助键中进行查找,然后进入PK以获得第三列。之后,分类并交付一行
更改PK可以避免额外的查找。这一变化不应该有“负面影响”
如果表中有数百万行,则可能有1000行
PRIMARY KEY(name, env)
( SELECT `enabled`
FROM `features`
WHERE `name` = 'some_featuere'
AND `env` = 'all'
ORDER BY `enabled` ASC
limit 1
)
UNION DISTINCT
( SELECT `enabled`
FROM `features`
WHERE `name` = 'some_featuere'
AND `env` = 'qa'
ORDER BY `enabled` ASC
limit 1
)
ORDER BY `enabled`
LIMIT 1;
`env` SET('local', 'qa', 'staging', 'production') NOT NULL,
PRIMARY KEY (`name`)
AND `env` IN('all', 'qa')
AND env = 'qa'