如果要存储布尔值或标志,基本上有三个选项:
- 单个列
这反映在您上面的示例中。优点是您将能够将索引放在您打算最常用于查找的标志上。缺点是这会占用更多空间(因为可以分配的最小列大小是 1 字节。)
但是,如果您的列名确实是 field_20、field_21 等。那么这绝对不是要走的路。编号的列表示您应该使用其他两种方法中的任何一种。
- 位掩码
如上所述,您可以将多个值存储在单个整数列中。BIGINT 列最多可为您提供 64 个可能的标志。
值将类似于: UPDATE table SET flags=b'100'; 更新表 SET flags=b'10000';
然后该字段看起来像:10100
这将表示设置了两个标志值。要查询任何特定的标志值集,你会做
SELECT flags FROM table WHERE flags & b'100';
这样做的好处是您的标志在空间上非常紧凑。缺点是您不能在字段上放置索引,这将有助于提高搜索特定标志的性能。
- 一对多关系
这是您创建另一个表的地方,那里的每一行都会有它链接到的行的 id 和标志:
CREATE TABLE main ( main_id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, );
CREATE TABLE 标志( main_id INT UNSIGNED NOT NULL,名称 VARCHAR(16) );
然后,您将在标志表中插入多行。
优点是您可以使用索引进行查找,并且每行可以有任意数量的标志,而无需更改架构。这最适用于稀疏值,其中大多数行没有值集。如果每一行都需要定义所有标志,那么这不是很有效。
对于性能比较,您可以阅读我写的关于该主题的博客文章:
设置性能比较
此外,当您问哪个是“最佳”时,这是一个非常主观的问题。最擅长什么?这完全取决于您的数据是什么样的,您的需求是什么以及您希望如何查询它。
请记住,如果您想执行如下查询:SELECT * FROM table WHERE some_flag=true
仅当少数行设置了该值时,索引才会对您有所帮助。如果表中的大多数行的 some_flag=true,那么 mysql 将忽略索引并进行全表扫描。