Хранение шестнадцатеричных значений в двоичном виде в MySQL - PullRequest
13 голосов
/ 11 ноября 2009

Я думал о том, как я храню пароли в моей базе данных: соответствующим образом соленые строки SHA1 в поле CHAR (40). Однако, поскольку символьные данные на самом деле представляют собой просто шестнадцатеричное представление 160-битного числа, я подумал, что было бы лучше сохранить его как BINARY (20).

CREATE TABLE users (
    password BINARY(20)
    /* snip */
);

INSERT INTO users (password) VALUES (UNHEX(SHA1('mypassword'));

На мой взгляд, одним из преимуществ этого подхода является то, что он вдвое уменьшает размер этого поля, но я могу предположить, что, возможно, есть и некоторые недостатки.

Каково ваше мнение?

Ответы [ 6 ]

26 голосов
/ 11 ноября 2009

Мы использовали двоичный файл для тонны различных идентификаторов в нашей базе данных, чтобы сэкономить место, так как большинство наших данных состояло из этих идентификаторов. Поскольку кажется, что вам не нужно экономить место (так как это просто пароли, а не какой-то другой элемент огромного масштаба), я не вижу никакой причины использовать двоичный файл здесь.

Самой большой проблемой, с которой мы сталкивались, было постоянно раздражающее отображение двоичных данных в консоли (каждый раз, когда вы нажимаете кнопку select *, вы слышите миллион звуковых сигналов), и вам всегда нужно выбирать HEX () или вставлять UNHEX () Это боль.

Наконец, если вы смешаете и сопоставите (по ошибке) двоичный файл и HEX / UNHEX и соедините это значение, вы можете сопоставить записи, которые вы никогда не намеревались.

7 голосов
/ 11 ноября 2009

Вот мое расстройство:

  1. Если вы используете строки вместо двоичных, используйте поле фиксированной длины. Поскольку все алгоритмы хэширования выводят фиксированную длину, вы можете сэкономить там немного места.
  2. Поскольку вы проводите только сравнение на равенство, индексы не нужны. Двоичные поля не имеют типа сопоставления или набора символов.
  3. Типы столбцов BINARY не содержат нечетных предостережений при хранении, как в BLOB.
  4. Каждый шестнадцатеричный символ представляет 4 бита в 8 (или 7) битах, которые он потребляет. Это означает, что двоичное хранилище в два раза эффективнее.
  5. САМОЕ ВАЖНОЕ: Если вы не работаете во встроенной системе, где каждый байт имеет значение, не делайте этого. Наличие представления персонажа позволит вам лучше отладить. Кроме того, каждый раз, когда разработчик работает над такой проблемой, я задаюсь вопросом, почему. Каждое архитектурное решение, подобное этому, имеет свои недостатки, и, похоже, это решение не добавляет ценности вашему проекту.
  6. Вы всегда можете преобразовать в BINARY позже с помощью простого сценария SQL.

Короче говоря, используйте текстовое поле фиксированной длины. Подсчет байтов в текущем мире не принесет пользы, особенно когда легко добиться изменений.

Надеюсь, это поможет.

2 голосов
/ 28 сентября 2012

Это старый вопрос, но я заметил, что никто не упомянул подтверждение данных как преимущество для столбца BINARY. В частности, можно сохранить недопустимое значение в столбце CHAR (40), используя символы, которые не являются шестнадцатеричными цифрами (0-9, a-f).

Вы все еще можете вставить неправильное значение в столбец BINARY (например, если вы забудете вызвать UNHEX), но вам никогда не придется рассматривать чтение значения из базы данных, которое не анализируется правильно.

2 голосов
/ 23 октября 2011

Если вы хотите простой способ хранить двоичные файлы в sql ... вы можете конвертировать в hex ранее. Проверьте эту страницу: http://kekoav.com/blog/36-computers/58-uuids-as-primary-keys-in-mysql.html

Конвертировать в гекс, снять "-" и поставить "0x" перед строкой. Mysql будет понимать как байтовый контент.

Пример: INSERT INTO для пользователей SET password = 0x1e8ef774581c102cbcfef1ab81872213

2 голосов
/ 11 ноября 2009

Экономия места на жестком диске при хранении хешированных паролей в двоичном, а не в виде varchar, вероятно, незначительна. Сколько пользователей вы, вероятно, будете иметь в этой таблице? Умножьте это на разницу в пространстве между BINARY(20) и VARCHAR(n), и я думаю, вы обнаружите, что это не значительная экономия. Лично я предпочел бы шестнадцатеричное представление, потому что по крайней мере я могу напечатать его в запросе, если во время разработки я выполняю какую-то специальную операцию или пишу модульный тест для проверки операций, связанных с паролем. Шестнадцатеричный код несколько удобнее для чтения, чем двоичный, если мне случается загружать дамп данных в текстовом редакторе и т. Д. Суть в том, что шестнадцатеричное представление было бы более удобным во время цикла разработки.

0 голосов
/ 11 ноября 2009

Зачем изобретать велосипед? Почему бы не использовать CHAR(41), как таблица `mysql.user '? Это широко известный формат, поэтому будущие сопровождающие не будут ломать голову над вашей специальной схемой? Облегчите всем задачу, просто отметив «как пароли MySQL».

...