Я слышал слух, что при вставке двоичных данных (файлы и такой) в MySQL, необходимо использовать bin2hex()
функционируйте и отправьте его как КОДИРОВАННОЕ ШЕСТНАДЦАТЕРИЧНЫМИ ЧИСЛАМИ значение, вместо того, чтобы просто используйте 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 обрабатывает большие строки по сравнению с тем, как он обрабатывает КОДИРОВАННЫЕ ШЕСТНАДЦАТЕРИЧНЫМИ ЧИСЛАМИ значения
Однако мне нелегко подтверждать это. Все мои тесты указывают на точное противоположное; то, что bin2hex
метод на ~85% медленнее и использует памяти на ~24% больше.
(Я тестирую это на PHP 5.3, MySQL 5.1, Win7 x64 - Используя довольно простой цикл вставки.)
Например, этот график показывает частное использование памяти процесса mysqld, в то время как тестовый код работал:
(источник: advefir.com)
У кого-либо есть какой-либо explainations или reasources, который разъяснил бы это?
Спасибо.
Для меня это звучит как городская легенда.
bin2hex ()
отображает каждый байт на входе в два байта на выходе ( 'a'
-> '61'
), поэтому вы должны заметить значительное увеличение памяти сценария, выполняющего запрос - он должен использовать как минимум столько же памяти, сколько байтовая длина вставляемых двоичных данных.
Кроме того, это означает, что выполнение bin2hex ()
с длинной строкой занимает намного дольше, чем выполнение mysql_real_escape string ()
, что, как объясняется в Документация MySQL - просто экранирует 6 символов: NULL
, \ r
, \ n
, \
, ,
и «Control-Z».
Это было для части PHP, теперь для MySQL: серверу необходимо выполнить обратную операцию для правильного хранения данных. Реверсирование любой из функций занимает почти столько же времени, сколько и исходная операция - обратная функция mysql_real_escape_string ()
должна заменить экранированные значения ( \\
) на неэкранированные ( \
), тогда как в обратном порядке bin2hex ()
потребуется заменить каждый байтовый кортеж новым байтом.
Поскольку вызов mysql_real_escape_string ()
для двоичных данных безопасен (согласно MySQL и документации PHP , или даже если учесть, что операция не выполняет никаких других преобразований, кроме перечисленных выше) было бы совершенно бессмысленно выполнять такую дорогостоящую операцию.
Шестнадцатеричная строка значительно длиннее соответствующей двоичной строки. Просто время передачи и копирование внутри памяти PHP и MySQL может помочь.
Честно говоря, я не эксперт по базовой реализации, но не лучше ли вообще не передавать данные внутри SQL, а использовать, например, Привязка параметра PDOStatement
? Может быть, кто-то более знающий здесь сможет подтвердить, действительно ли это приведет к отправке данных в виде двоичной строки, вне любого оператора SQL, или же PDO просто выполняет экранирование и манипуляции со строкой запроса под капотом.
В любом случае, вы сразу получаете преимущество безопасности (и простоты).
Я сам тестировал это и получил довольно стабильные результаты. (Хотя мои тесты немного грубоваты.)
Я протестировал три компьютера
Пока тесты на всех трех платформах показали одни и те же вещи:
bin2hex
в X '...'
) используется больше памяти, в среднем, чем при использовании экранированной двоичной строки ( mysql_real_escape_string
для необработанных данных) . - Это похоже на MyISAM и InnoDB. Тест представлял собой простой цикл, который экранировал или закодировал необработанные данные в шестнадцатеричном коде (изображение размером 2,4 МБ, полученное один раз в верхней части сценария) , построил строку запроса и выполнил ее через функции mysql_query
или mysqli :: query
. - Я тестировал оба расширения. Похоже, никакой разницы не было.
Я поместил результаты Ubuntu 10.04 (№3) в электронные таблицы. Результаты на машине с Ubuntu 9.10 (# 2) были почти такими же, поэтому я не стал их настраивать:
(Наконец-то повод для правильного тестирования Google Docs! XD)
Эти графики показывают использование частной памяти процессом mysqld
в Win7 ( №1) машина.