Хранение шестнадцатеричных значений как двоичных в 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".