Я создаю мобильное приложение. Я использую PHP и MySQL для написания бэкэнд – REST API.
Если мне нужно хранить около 50-60 булевых значений в таблице «Отчеты» (пользователи должны проверять вещи в форме) в мобильном приложении, я сохраняю значения (0/1) в простом массиве. В моей таблице MySql я должен создать другой столбец для каждого логического значения или достаточно, если я просто использую строку или Int, чтобы сохранить ее как «число», например «110101110110111 …»?
Я получаю и помещаю данные в JSON.
ОБНОВЛЕНИЕ 1: все, что мне нужно сделать, это проверить, все ли 1, если один из них равен 0, то это «проблема». Через 2 года эта таблица будет содержать около 15 000-20 000 строк, она должна быть очень быстрой и максимально экономичной.
ОБНОВЛЕНИЕ 2: С точки зрения скорости решение быстрее? Создание отдельных столбцов и сохранение их в виде строки / двоичного типа. Что делать, если я должен проверить, какие из них – 0? Является ли это отличным решением, если я сохраню его как «число» в одном столбце, и если это не «111..111», то отправьте его в мобильное приложение как JSON, где я проанализирую значение и проанализирую его на устройстве пользователя? Предположим, мне приходится иметь дело с 50K строк.
Заранее спасибо.
Отдельный столбец на значение более гибкий, когда дело доходит до поиска.
Отдельная таблица ключей / значений более гибкая, если разные строки имеют разные коллекции булевых значений.
И если
то использование текстовых строк типа «1001010010» и т. д. является хорошим способом их хранения. Вы можете искать это
WHERE flags <> '11111111'
чтобы найти нужные вам строки.
Вы можете использовать столбец BINARY с одним битом на флаг. Но ваш стол будет проще использовать для случайных запросов и проверки глазного яблока, если вы используете текст. Экономия пространства от использования BINARY вместо CHAR не будет существенной, пока вы не начнете хранить много миллионов строк.
edit Следует сказать: каждый раз, когда я создавал что-то подобное с массивами логических атрибутов, позже я был разочарован тем, насколько он был негибким. Например, предположим, что это был каталог лампочек. На рубеже тысячелетий булевы флаги могли быть такими, как
screw base halogen mercury vapor low voltage
Затем все меняется, и мне нужно больше логических флагов, например,
LED CFL dimmable Energy Star
и т. д. Внезапно мои типы данных не достаточно велики, чтобы удерживать то, что мне нужно для их хранения. Когда я писал, что «ваш список булевых значений более или менее статичен», я имел в виду, что вы не можете рассчитывать на изменение характеристик лампочек в течение всего срока службы вашего приложения.
Таким образом, отдельная таблица атрибутов может быть лучшим решением. У этого были бы следующие столбцы:
item_id fk to item table -- pk attribute_id attribute identifier -- pk attribute_value
Это в конечном счете гибкое. Вы можете просто добавить новые флаги. Вы можете добавлять их к существующим элементам или к новым элементам в любое время в течение всей жизни вашего приложения. И каждый элемент не нуждается в одном наборе флагов. Вы можете написать «какие предметы имеют ложные атрибуты?» запрос выглядит так:
SELECT DISTINCT item_id FROM attribute_table WHERE attribute_value = 0
Но вы должны быть осторожны, потому что запрос «какие элементы имеют отсутствующие атрибуты» намного сложнее написать.
Для вашей конкретной цели, когда любой нулевой флаг является проблемой (исключение), и большинство записей (например, 99%) будет «1111 … 1111», я не вижу причин для их хранения. Я бы предпочел создать отдельную таблицу, в которой хранятся только флаги без отметки. Таблица может выглядеть так: 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;
Вы можете получить лучший поиск из выделенных столбцов, для каждого логического, но мощность невелика, и даже если вы индексируете каждый столбец, это приведет к честному обходу или сканированию.
Если вы просто ищете HIGH-VALUES 0xFFF …. то определенно растровое изображение, это решает вашу проблему с мощностью (за обновление OP). Это не похоже на то, что вы проверяете паритет … Однако дерево будет сильно искажено до ВЫСОКИХ ЦЕННОСТЕЙ, если это нормально и может создать горячую точку, склонную к разбиению узлов на вставки.
Бит-сопоставление и использование побитовых масок оператора сэкономит место, но их нужно будет выровнять по байту, поэтому может быть неиспользуемый «подсказка» (возможно, для будущих полей), поэтому маска должна иметь поддерживаемую длину или поле, дополненное 1s.
Это также добавит сложности вашей архитектуре, что может потребовать индивидуального кодирования, на заказные стандарты.
Вам необходимо провести анализ важности любого поиска (обычно вы не можете ожидать поиска всего или даже любого из дискретных полей).
Это очень распространенная стратегия денормализации данных, а также для настройки запроса обслуживания для конкретных клиентов. (Там, где некоторые reponses более толстые, чем другие для одной и той же транзакции).