我正在构建移动应用程序我使用PHP& MySQL编写后端 - REST API。
如果我必须在我的移动应用程序中将名为" Reports"(用户必须检查表单中的内容)的表中存储大约50-60个布尔值,我将值(0/1)存储在一个简单的数组。在我的MySql表中,我应该为每个布尔值创建一个不同的列,或者如果我只是使用字符串或Int将其存储为"数字"喜欢" 110101110110111 ..."?
我使用JSON获取数据。
更新1:我所要做的就是检查一切是否为1,如果其中一个为0则表示问题是"问题"。在2年内,这个表将有大约15.000-20.000行,它必须非常快,并且尽可能节省空间。
更新2:在速度方面哪个解决方案更快?制作单独的列并将其存储为字符串/二进制类型。如果我必须检查哪些是0,该怎么办?如果我将它存储为"数字"这是一个很好的解决方案吗?在一栏中,如果不是" 111..111"然后将其作为JSON发送到移动应用程序,我在其中解析该值并在用户的设备上进行分析?让我们说我必须处理50K行。
提前致谢。
答案 0 :(得分:13)
在搜索时,每个值的单独列更灵活。
如果不同的行具有不同的布尔值集合,则单独的键/值表会更灵活。
而且,如果
WHERE flags <> '11111111'
找到您需要的行。
您可以使用每个标志一位的BINARY列。但是,如果您使用文本,您的表格将更容易用于临时查询和眼球检查。在您开始存储数百万行之前,使用BINARY而不是CHAR节省的空间将非常重要。
编辑必须要说的是:每当我用布尔属性数组构建这样的东西时,我后来对它的灵活性感到失望。 。例如,假设它是一个灯泡目录。在千禧年之际,布尔标志可能就像
一样screw base
halogen
mercury vapor
low voltage
然后,事情发生了变化,我发现自己需要更多的布尔标志,比如
LED
CFL
dimmable
Energy Star
等。突然之间,我的数据类型不足以容纳我需要它们持有的东西。当我写&#34;你的布尔值列表或多或少是静态的&#34;我的意思是你没有合理的期望在应用程序的生命周期中有类似灯泡特性的变化。
因此,单独的属性表可能是更好的解决方案。它将包含以下列:
item_id fk to item table -- pk
attribute_id attribute identifier -- pk
attribute_value
这最终是灵活的。你可以添加新的标志。您可以在应用程序的生命周期中随时将它们添加到现有项目或新项目中。并且,每个项目都不需要相同的标志集合。你可以写&#34;哪些项目有任何虚假属性?&#34;查询如下:
SELECT DISTINCT item_id FROM attribute_table WHERE attribute_value = 0
但是,你必须要小心,因为查询&#34;哪些项目缺少属性&#34;写起来要困难得多。
答案 1 :(得分:11)
出于特定目的,当任何零标志是一个问题(例外)并且大多数条目(如99%)将是&#34; 1111 ... 1111&#34;时,我看不出任何理由存储它们。我宁愿创建一个单独的表,只存储未经检查的标志。该表可能如下所示: uncheked_flags(user_id,flag_id)。在另一个表中,您可以存储标志定义: flags(flag_id,flag_name,flag_description)。
然后您的报告就像SELECT * FROM unchecked_flags
一样简单。
更新 - 可能的表格定义:
CREATE TABLE `flags` (
`flag_id` TINYINT(3) UNSIGNED NOT NULL AUTO_INCREMENT,
`flag_name` VARCHAR(63) NOT NULL,
`flag_description` TEXT NOT NULL,
PRIMARY KEY (`flag_id`),
UNIQUE INDEX `flag_name` (`flag_name`)
) ENGINE=InnoDB;
CREATE TABLE `uncheked_flags` (
`user_id` MEDIUMINT(8) UNSIGNED NOT NULL,
`flag_id` TINYINT(3) UNSIGNED NOT NULL,
PRIMARY KEY (`user_id`, `flag_id`),
INDEX `flag_id` (`flag_id`),
CONSTRAINT `FK_uncheked_flags_flags` FOREIGN KEY (`flag_id`) REFERENCES `flags` (`flag_id`),
CONSTRAINT `FK_uncheked_flags_users` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`)
) ENGINE=InnoDB;
答案 2 :(得分:1)
你可以使用专用列获得更好的搜索,对于每个布尔值,但基数很差,即使你索引每一列,它也会涉及相当多的遍历或扫描。 / p>
如果你只是寻找高价值0xFFF ....那么绝对是位图,这解决了你的基数问题(每次OP更新)。它不像你正在检查奇偶校验......如果这是正常的话,树会严重偏向高值,并且可能会在插入时产生易于节点分裂的热点。
位映射和使用按位运算符掩码将节省空间,但需要与一个字节对齐,因此可能存在未使用的&#34;提示&#34; (可能为未来字段供应),因此掩码必须是保持长度或填充1s的字段。
它还会增加您的架构的复杂性,这可能需要定制编码,定制标准。
您需要对任何搜索的重要性进行分析(您通常不希望搜索所有搜索。甚至任何离散字段)。
这是对数据进行非规范化以及针对特定客户端调整服务请求的一种非常常见的策略。 (对于同一交易,某些回复比其他回报更胖)。