Хранение шестнадцатеричных значений как двоичных в MySQL
Я думал о том, как я храню пароли в своей базе данных: правильно соленые строки SHA1 в поле CHAR (40). Однако, поскольку символьные данные в них фактически представляют собой шестнадцатеричное представление 160-битного числа, я подумал, что лучше сохранить его как BINARY (20).
CREATE TABLE users (
password BINARY(20)
/* snip */
);
INSERT INTO users (password) VALUES (UNHEX(SHA1('mypassword'));
Как я вижу, одним из преимуществ этого подхода является то, что он уменьшает размер этого поля, но я могу представить, что, возможно, есть и некоторые недостатки.
Каково ваше мнение?
Ответы
Ответ 1
Мы использовали двоичный код для тонны различных идентификаторов в нашей базе данных, чтобы сэкономить место, поскольку большинство наших данных состояло из этих идентификаторов. Так как вам не кажется, что вам нужно сэкономить место (поскольку это просто пароли, а не какой-то другой элемент огромного масштаба), я не вижу причин использовать здесь двоичный код.
Самая большая проблема, с которой мы столкнулись, была постоянно, досадно, когда в консоли отображались двоичные данные (каждый раз, когда вы набираете select *, вы слышите миллион звуковых сигналов), и вам всегда нужно выбирать HEX() или вставлять UNHEX(), что является болью.
Наконец, если вы смешиваете и сопоставляете (по ошибке) двоичный и HEX/UNHEX и присоединяетесь к этому значению, вы можете сопоставлять записи, которые вы никогда не планировали.
Ответ 2
Вот мой пробой:
- Если вы используете строки вместо двоичных, используйте поле с фиксированной длиной. Поскольку хеширующие альгоны выдает фиксированную длину, вы можете сэкономить себе некоторое пространство.
- Поскольку вы выполняете сравнение равенства, нет необходимости в индексах. Двоичные поля не имеют типа сортировки или набора символов.
- Типы BINARY-столбцов не имеют особых ограничений хранения, таких как BLOB файлы.
- Каждый шестнадцатеричный символ представляет 4 бита в 8 (или 7) битах, которые он потребляет. Это означает, что двоичное хранилище вдвое эффективнее.
- САМЫЙ ВАЖНЫЙ: Если вы не работаете во встроенной системе, где подсчитывается каждый байт, не делайте этого. Наличие символьного представления позволит вам лучше отлаживать. Плюс, каждый раз, когда разработчик работает над такой проблемой, я должен задаться вопросом, почему. Каждое архитектурное решение, подобное этому, имеет компромиссы, и это не похоже, что это добавляет ценность вашему проекту.
- Вы всегда можете преобразовать в BINARY с помощью простого SQL script.
Короче говоря, используйте текстовое поле с фиксированной длиной. Нет никакой выгоды для подсчета байтов в текущем мире, особенно когда изменения легко достичь.
Надеюсь, это поможет.
Ответ 3
Экономия пространства на жестком диске при хранении ваших хешированных паролей как двоичных, а не varchar, вероятно, незначителен. Сколько у вас пользователей в этой таблице? Умножьте это на разницу в пространстве между BINARY(20)
и VARCHAR(n)
, и я думаю, вы обнаружите, что это не значительная экономия. Лично я бы предпочел шестнадцатеричное представление, потому что, по крайней мере, я могу ввести его в запрос, если я делаю какую-то специальную операцию во время разработки или пишу unit test для проверки операций, связанных с паролем. Hex несколько читабельнее, чем двоичный, если я загружаю дамп данных в текстовом редакторе и т.д. Моя нижняя строка заключается в том, что шестнадцатеричное представление было бы более удобным в течение цикла разработки.
Ответ 4
Если вам нужен простой способ сохранить двоичный файл в sql..., вы можете преобразовать его в hex раньше.
Проверьте эту страницу:
http://kekoav.com/blog/36-computers/58-uuids-as-primary-keys-in-mysql.html
Преобразуйте в шестнадцатеричный, снимите "-" и поставьте "0x" перед строкой. Mysql будет понимать как содержимое байта.
Пример:
INSERT INTO users SET пароль = 0x1e8ef774581c102cbcfef1ab81872213
Ответ 5
Это старый вопрос, но я заметил, что никто не упомянул проверку данных как преимущество для столбца BINARY. В частности, можно хранить недопустимое значение в столбце CHAR (40), используя символы, которые не являются шестнадцатеричными цифрами (0-9, a-f).
Вы все равно можете вставить неправильное значение в столбец BINARY (например, если вы забыли вызвать UNHEX), но вам не придется рассматривать чтение значения из базы данных, которая не анализируется правильно.
Ответ 6
Зачем изобретать колесо? Почему бы не использовать CHAR(41)
, как используется таблица `mysql.user '? Это хорошо известный формат, поэтому любые будущие сопровождающие не будут царапать свои головы по вашей специальной схеме? Упростите всех, просто отметив "как пароли MySQL".