Лучший способ хранить большие файлы в базе данных MySQL? - PullRequest
2 голосов
/ 09 октября 2010

У меня есть PHP-скрипт, с помощью которого вы можете загружать очень большие файлы (до 500 МБ), и содержимое файла сохраняется в базе данных MySQL.В настоящее время я делаю что-то вроде этого:

mysql_query("INSERT INTO table VALUES('')");

$uploadedfile = fopen($_FILES['file']['tmp_name'], 'rb');
while (!feof($uploadedfile)) {
    $line = mysql_escape_string(fgets($uploadedfile, 4096));
    mysql_query("UPDATE table SET file = CONCAT(file, '$line') WHERE something = something");
}
fclose($uploadedfile);

Это, конечно, чертовски много SQL-запросов.

Я сделал это, а не что-то вроде

$file = file_get_contents($_FILES['file']['tmp_name']);
mysql_query("INSERT INTO table VALUES('$file')");

, потому чтоэто заняло бы столько памяти, сколько было у файла, и казалось, что лучше делать больше запросов sql, чем использовать 500 МБ памяти.
Однако должен быть лучший способ.Должен ли я пойти дальше и сделать это путем file_get_contents, или есть лучший способ, чем CONCAT, или способ, которым я делаю это сейчас, является меньшим из всех зол?

Ответы [ 6 ]

3 голосов
/ 09 октября 2010

Я всегда храню свои файлы на сервере и храню их расположение в базе данных.

2 голосов
/ 24 апреля 2015

Вы правы, в некоторых случаях файловая система не может выполнить эту работу.Поскольку базы данных имеют такие функции, как блокировка, репликация, целостность, отсутствие ограничений на количество строк и т. Д. И т. Д., Которых нет в файловой системе.

Кроме того, резервное копирование / восстановление / перенос системы становится болеесложный и не может быть безопасно выполнен на работающем сервере (риск несогласованности и потери данных).Или, по крайней мере, гарантировать это очень сложно в конфигурации DB + FS.

А как насчет перехода с ОС на основе разделителя "/" на ОС на основе \?Вам необходимо обновить все ваши пути.

Ваш метод выглядит правильным, но 4096-байтовый срез слишком мал.Например, у Mysql не возникнет проблем при работе со срезами 256 КБ.

Кроме того, я бы не стал объединять, а скорее сохранял бы каждый фрагмент как отдельную запись.В базе данных могут возникнуть проблемы с хранением огромных файлов в одной записи, и это может привести к ограничениям, упомянутым в других ответах.

Сохранение данных нарезанных позволит потоковую передачу контента, даже не сохраняя, например, все данные в памяти.Таким образом, размер сохраняемого файла практически не ограничен.

1 голос
/ 09 октября 2010

Это на самом деле не будет работать (по умолчанию) с mySQl, потому что это вызовет большой запрос размером 500 МБ.

$file = file_get_contents($_FILES['file']['tmp_name']);
mysql_query("INSERT INTO table VALUES('$file')");

, потому что для max_allowed_packet установлено значение 16777216. Вам либо потребуетсячтобы увеличить или разделить его на куски размером менее 16 МБ (минус запрос ~ 500-1000 байт для строки запроса).

Чтобы узнать max_allowed_packet вашего сервера mysql, выполните запрос

SELECT @@global.max_allowed_packet
0 голосов
/ 05 декабря 2014

Вы можете использовать это:

http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_load-file Это также дает простой пример запроса.

0 голосов
/ 09 октября 2010

Мне еще предстоит увидеть приложение, которое на самом деле должно хранить файлы в реляционной базе данных.

Существует значительное количество свободно доступных, мощных баз данных, разработанных и оптимизированных специально для хранения / извлечения файлов. Они называются файловыми системами

Храните ваши файлы в вашей файловой системе и ваши метаданные в СУБД.

Вы беспокоитесь об использовании 500 МБ памяти при вставке,и не понятно почему.В конечном итоге вам захочется вернуть эти файлы из базы данных, и я не думаю, что вы найдете способ считывать данные файлов кусками.

0 голосов
/ 09 октября 2010

Я хотел бы представить, что наиболее эффективный способ сделать это - выполнить всю проверку в сценарии ДО ТОЧКИ вставки, затем выложить оболочку и выполнить перемещение файла загруженного временного файла $ FILES, переданного в MySQL запрос на вставку командной строки. Вы бы хотели, чтобы кто-то лучше в bash, чем я, проверил это, но, похоже, это в значительной степени устранит проблему с памятью?

...