2010-10-08 6 views
2

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

+5

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

+0

Если вы скажете: «Я хочу водить машину по автостраде с помощью только колесных дисков, без шин. Ответ, который даст вам большинство людей, это «Не надо». Если вы спросите, как сделать тупое дело с кодом, большинство разработчиков, которые знают их материал, ответят аналогичным образом. Это доброта, а не оскорбление. – curtisdf

ответ

3

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

+1

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

+1

@ nickolas. Не могли бы вы объяснить, почему? Моя первая мысль была файловая система хороша для файла ... –

+1

Хороший ответ. Хранение всего файла в таблице - это как парковка вашего автомобиля в кармане - лучше припарковать автомобиль в гараже и положить ключ в карман, то же самое с файлами, лучше хранить файл в папке и его расположение в таблице , –

0

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

1

Это не будет работать (по умолчанию) с 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

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

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

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

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

+0

Это данные. Он находится в базе данных. Вместо этого вы защищаете хранение некоторых данных в одной системе, а остальные - в другом. Вы собираетесь хранить данные в двух параллельных системах. Таким образом, у вас есть потенциал для устранения этих двух систем. У вас есть две точки отказа. У вас также есть потенциал для использования, поскольку ваше приложение должно обязательно иметь возможность писать в файловую систему. Таким образом, существует больше возможностей для написания исполняемого файла, который каким-то образом выполняется. – Charles

+0

@Charles - Все это относится к серьезным проблемам. Однако, по моему опыту, попытка сохранить любое значительное количество данных блоба в РСУБД неизбежно приводит к боли. Файловые системы легко разбиваются на разделы, легко реплицируются/создаются резервные копии (rsync) и выполняются для использования. В эти дни вы можете использовать что-то вроде S3, а кто-то еще беспокоится о отказоустойчивости и доступности. Иными словами, причина в том, что Amazon не реализовал S3 с RDBMS на back-end для хранения памяти. – timdev

2

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

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

Что касается переноса с ОС на основе «/» на основе «\» на основе одного? Вам необходимо обновить все ваши пути.

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

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

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

Смежные вопросы