|
|
Регистрация Восстановить пароль |
Повторная активизация e-mail |
Регистрация | Задать вопрос |
Заплачу за решение |
Новые сообщения |
Сообщения за день |
Расширенный поиск |
Правила |
Всё прочитано |
|
|
Опции темы | Поиск в этой теме |
22.04.2011, 02:34 | #1 |
Пользователь
Регистрация: 17.04.2011
Сообщений: 11
|
Хранение логических переменных в одном числе
Решил поделиться одной идеей по хранению нескольких значений в одной переменной.
Задача заключалась в сохранении / считывании различных настроек пользователя, которые являлись логическими переменными (т.е. выбор заключался только в “да” либо “нет”). Значений было порядка 20-ти, а поэтому желания хранить каждое значение в отдельном столбце таблицы базы данных не было (таблица на тот момент уже содержала много столбцов, а создавать отдельную для настроек желания так же не было). Решение пришло неожиданно. В памяти всплыло уже найденное решение, используемое для указания прав на файлы в UNIX-подобных системах. Так три числа 6 / 4 / 4 содержат информацию о правах для владельца файла / группы / других (110 / 100 / 100). Итак, используя двоичную систему счисления, возможно все 20 необходимых параметров хранить в одном числе. Пример: 00100000000000000001 (2) = 131073 (10) Слева показано число в двоичной системе (20 значений, каждое из которых может быть “0” или “1”), а справа - то же число но в десятичной системе для хранения в базе. Чтобы было нагляднее, далее приведен пример реализации решения при работе с PHP и MySQL. Структупра MySQL базы данных: Код:
Нумерацию параметров будем вести с конца, т.е. если у пользователя 1-я, 3-я и 6-я опции выбраны, тогда значение будет следующим: 000100101 - значение user_options в двоичной системе 987654321 - порядковый номер Следующая того чтобы каждый раз не обращаться базе по каждому параметру, напишем функцию считывания десятичного значения: //$user_id - ID пользователя, для которого ищется значение параметров //функция возвращает десятичное число, которое содержит значения всех параметров пользователя //если пользователя такого нет - тогда функция вернёт false PHP код:
затем функцию нахождения значения для указанного параметра //$opt_ind - порядковый номер параметра (отсчет справа), //$int_val - десятичное значение, найденное функцией getIntOptions($user_id) //фунция возвращает значение указанного параметра ("0" или "1") function getOptionFromInt($opt_ind, $int_val) { $cur_options = decbin($int_val); if ((strlen($cur_options) - $opt_ind) < 0) { $cur_val = 0; } else { $cur_val = substr($cur_options, strlen($cur_options) - $opt_ind, 1); } return $cur_val; } Используя предыдущие две функции можно найти значение определенного параметра пользователя: PHP код:
Для указания и сохранения параметра используем функцию ниже: //$user_id - ID пользователя, $opt_ind - порядковый номер (справа) параметра в опциях, $val - значение, которое нужно присвоить параметру ("0" либо "1") //функция возвращает true при успешном присвоении; в противном случае - false PHP код:
|
22.04.2011, 02:35 | #2 |
Пользователь
Регистрация: 17.04.2011
Сообщений: 11
|
---
Для проверки параметра пользователя непосредственно в запросе MySQL можно использовать следующее условие: Код:
Например, результатом следующей операции Код:
Код:
P.S. Описанные функции и запросы были протестированы, проблем не встречал. P.P.S. Если значения не только “да” / “нет” (1 / 0), а к примеру 3-4 варианта для одной опции, тогда вполне можно использовать ту же логику но с несколькими параметрами (для одного параметра будет уделяться несколько ячеек). |
22.04.2011, 08:23 | #3 |
Старожил
Регистрация: 25.02.2007
Сообщений: 4,160
|
Идея не нова.... упаковка параметров в числа итд ... часто встречается в ассабмлере ))))) где нжна такая оптимизация. В случае с Мускулем при современных технологиях - на экономию в 10-ки и сотни байт вряд ли кто-то обратит внимание, особенно если извлечение этих параметров столь ресурсоемко.
А так - имеет место жить такой способ, единствоенное как у него с расширяемостью? например не 64 понадобилось а 164 параметра? - как бестро и безболезнено поменять в коде запросы, а в базе значения? |
22.04.2011, 09:31 | #4 |
Старожил
Регистрация: 19.04.2010
Сообщений: 2,702
|
AlexanderGalkin, убейте себя об стену.
Сначала Я подумал, что Вы взяли этот пример с Хабра (там его какой-то мудак представил как гениальное решение), но оказывается к такому решению могут прийти и обычные программисты. Проблема данного метода в том, что основан на идиотском представлении о хранении данных в БД. Вышеперечисленная задача легко и оптимально решается при помощи сессий и сериализации. |
22.04.2011, 12:03 | #5 |
Пользователь
Регистрация: 17.04.2011
Сообщений: 11
|
Не исключал такой реакци)
Просто хотел поделиться соображениями. Не судите строго. |
22.04.2011, 12:07 | #6 |
Пользователь
Регистрация: 17.04.2011
Сообщений: 11
|
ADSoft, для большего количества значений я делал отдельный столбец в базе (например, user_options_email), при этом стоит всего лишь подкорректировать функцию getOptionFromInt для указания параметра, с какой колонкой в таблице работаете.
Последний раз редактировалось AlexanderGalkin; 22.04.2011 в 12:09. |
22.04.2011, 12:11 | #7 |
Форумчанин
Регистрация: 20.05.2009
Сообщений: 506
|
Сам метод - не плох.
Но в контексте вашей задачи , имхо не удачен. Так как надо ведь ещё и хранить соответствие разряда числа- опция в настройке юзера. Последний раз редактировалось ssdm; 22.04.2011 в 13:16. |
22.04.2011, 12:18 | #8 |
Форумчанин
Регистрация: 20.05.2009
Сообщений: 506
|
AlexanderGalkin
Не лучше ли собирать ассоциативный массив из настроек, сериализировать его сохранять в бд ? |
22.04.2011, 12:34 | #9 |
Старожил
Регистрация: 19.04.2010
Сообщений: 2,702
|
Этот метод крайне плох.
Во-первых, сохранённые по отдельности значения в поля byte(1) будут занимать меньше места, чем строка данных. И работать с ними можно будет напрямую. Где экономия? не понятно. Во-вторых, MySQL работает нормально с таблицами, где много полей. У меня в проекте есть таблицы, где почти сотня полей - снижения скорости никакой. В-третьих, насколько Я понимаю, всё упирается в желание запихнуть в одну строку. Так создайте массив настроек, сериализуйте его и сохраняйте. При инициализации системы вытаскивайте его и помещайте в сессию, что бы в дальнейшем не обращаться к базе. Хотя лучше разбить на отдельные поля. |
22.04.2011, 14:24 | #10 | |
Пользователь
Регистрация: 17.04.2011
Сообщений: 11
|
По поводу сериализации согласен - метод хорош. Но есть необходимость администрирования базы. А по сему подскажите пожалуйста как построить запрос к базе в случае хранения ассоциативного массива в сериализированной строке?
Скажем, есть ID пользователя и нужно проверить что первая опция и пятая равны единице. По поводу работы MySQL c большим количеством столбцов - я не говорил что это плохо, либо есть недостатки. Но ИМХО - мне удобнее работать с обним столбцом, а не с 50-тью. И ещё один вопрос: Цитата:
|
|
|
Похожие темы | ||||
Тема | Автор | Раздел | Ответов | Последнее сообщение |
Хранение БД в одном файле | D_E_N | БД в Delphi | 3 | 18.07.2009 14:01 |
изменение нескольких переменных в одном методе. | goog | Общие вопросы по Java, Java SE, Kotlin | 5 | 01.03.2009 20:46 |
Прибавление логических функций | Slavik | Microsoft Office Excel | 19 | 26.01.2009 23:39 |
Использование логических функций | Клубничка | Microsoft Office Excel | 52 | 15.01.2009 15:01 |
Свой тип данных в Delphi - сверх длинные числа - хранение в переменных размером до 1 MB | KLaiM | Общие вопросы Delphi | 9 | 16.06.2007 09:13 |