Intereting Posts
Unserialize в Java – сериализованный php-объект PHP разделяет альтернативу? Алгоритм вычисления ряда будущих дат на основе частоты Запустить команду ipconfig с помощью php Использует microtime () для создания неудачных методов токена сброса пароля Система дружбы с Laravel: отношения Many to Many PHP: как я могу сортировать и фильтровать «массив», то есть объект, реализующий ArrayAccess? Мои файлы cookie доступны только на страницах PHP, на которые они установлены, это нормально? Алгоритм MySQL / PHP для расчета количества дней недели / недели (в месяц) Как загрузить длину видеофайла в Amazon S3? Производный класс, определенный позже в том же файле, «не существует»? Проверка XPath / Domdocument для дочернего объекта по имени класса Comet & PHP: Как использовать комету с системой PHP Chat? Сохранение файла cookie после запроса ajax для междоменного доступа «Разрешенная память .. исчерпана» при использовании readfile

Зачем использовать bin2hex при вставке двоичных данных из PHP в MySQL?

Я слышал слухи о том, что при вставке двоичных данных (файлов и т. Д.) В MySQL вам следует использовать bin2hex() и отправлять ее как значение в виде HEX, а не просто использовать mysql_real_escape_string в двоичной строке и использовать ее.

 // That you should do $hex = bin2hex($raw_bin); $sql = "INSERT INTO `table`(`file`) VALUES (X'{$hex}')"; // Rather than $bin = mysql_real_escape_string($raw_bin); $sql = "INSERT INTO `table`(`file`) VALUES ('{$bin}')"; 

Это предположительно по соображениям производительности. Что-то связано с тем, как MySQL обрабатывает большие строки по сравнению с тем, как он обрабатывает значения HEX-кода

Однако мне сложно это подтвердить. Все мои тесты указывают на точный oposite; что метод bin2hex ~ на 85% медленнее и использует на 24% больше памяти.
(Я тестирую это на PHP 5.3, MySQL 5.1, Win7 x64 – Использование простейшего простого цикла вставки).

Например, на этом графике показано использование частной памяти в процессе mysqld во время работы тестового кода:

Частные байты, используемые процессом mysqld http://img.ruphp.com/binary/priv_mem_cropped.gif

Есть ли у кого-нибудь какие-либо объяснения или объяснения, которые могли бы прояснить это?

Благодарю.

Для меня это звучит как городская легенда.

bin2hex() отображает каждый байт на вход в два байта на выходе ( 'a' -> '61' ), поэтому вы должны заметить значительное увеличение памяти скрипта, выполняющего запрос, – он должен использовать по меньшей мере столько же памяти больше как длина байта двоичных данных, подлежащих вставке.

Кроме того, это означает, что запуск bin2hex() в длинной строке занимает намного больше времени, чем запуск mysql_real_escape string() , который, как объясняется в документации MySQL, просто ускользает от 6 символов: NULL , \r , \n , \ , и and Control -Z».

Это было для части PHP, теперь для MySQL: серверу нужно выполнить обратную операцию для правильного хранения данных. Реверсирование любой из функций занимает почти столько же времени, сколько и исходная операция – обратная функция mysql_real_escape_string() требует замены экранированных значений ( \\ ) неэкранированными ( \ ), тогда как обратная bin2hex() должна будет заменить каждый и каждый байтовый кортеж с новым байтом.

Поскольку вызов mysql_real_escape_string() для двоичных данных является безопасным (согласно документации MySQL и PHP или даже если просто считать, что операция не делает никаких других преобразований, кроме перечисленных выше), было бы совершенно бессмысленно выполнять такую ​​дорогостоящую операцию ,

Я сам тестировал это, и я придумал довольно последовательные результаты. (Хотя мои тесты немного грубые).

Я проверил три компьютера

  1. Windows 7 (x64), PHP 5.3, MySQL 5.1
  2. Ubuntu 9.10 (x64) PHP 5.2, MySQL 5.1
  3. Ubuntu 10.04 (x32) PHP 5.3, MySQL 5.1

Пока тесты на всех трех платформах показали одинаковые тона:

  • Вставка в BLOB в 2 раза быстрее на MyISAM, чем на InnoDB. Разница, по-видимому, выше в бинарных строках, чем строки с HEX-кодом. (См. Приведенные ниже данные)
  • Использование HEX-кодированной строки ( bin2hex в X'...' ) использует в среднем больше памяти, чем использование двоичной строки с экранированием ( mysql_real_escape_string по необработанным данным) . – Это похоже на MyISAM и InnoDB.
  • Бинарная строка работает быстрее в MyISAM, но данные с индексом HEX быстрее на InnoDB.

Тест был в основном простой петлей, которая избегала или кодировала необработанные данные (изображение 2,4 MiB, полученное один раз в начале скрипта) , построило строку запроса и выполнило ее через функции mysql_query или mysqli::query . – Я тестировал оба расширения. Кажется, не было никакой разницы.

Я положил результаты из Ubuntu 10.04 (# 3) в электронные таблицы. Результаты от машины Ubuntu 9.10 (# 2) были почти такими же, поэтому я не стал их настраивать:
(Наконец, оправдание для проверки правильности документов Google! XD)

  • Двоичная строка в MyISAM
  • HEX-кодированная строка в MyISAM
  • Двоичная строка на InnoDB
  • Шестнадцатеричная строка на InnoDB

Эти графики показывают использование частной памяти процессом mysqld на машине Win7 (# 1).

  • Двоичная строка в MyISAM
  • HEX-кодированная строка в MyISAM
  • Двоичная строка на InnoDB
  • HEX-кодированная строка на InnoDB

Шестнадцатеричная строка значительно длиннее соответствующей двоичной строки. Просто время передачи и копирование его внутри памяти PHP и MySQL могут сделать трюк.

Честно говоря, я не эксперт по базовой реализации, но не лучше ли вообще не передавать данные внутри SQL, но используя, например, PDOStatement параметров PDOStatement ? Может быть, кто-то более осведомленный здесь может подтвердить, действительно ли это приведет к отправке данных как двоичной строки, вне любой инструкции SQL, или же PDO просто выполняет манипуляции с экранированием и строкой запроса под капотом.

В любом случае, вы получаете право на безопасность (и простоту) прямо там.

например, если вы столкнулись с аналогичной проблемой, описанной здесь: http://www.php.net/manual/en/function.mysql-real-escape-string.php#82015

например, хотя mysql_real_escape_string кажется «двоично-безопасным», вы не можете его использовать (в качестве примера) в сочетании с igbinary_serialize – неэрициализация просто завершится неудачей.

в этом случае вам нужно bin2hex перед вставкой данных в mysql.

Кроме того, обычно вы чаще читаете данные из mysql, чем вставляете 🙂