Потоковый файл в MySQL в C - PullRequest
       14

Потоковый файл в MySQL в C

0 голосов
/ 19 февраля 2012

Я искал повсеместно для потоковой передачи файла в MySQL, используя C, и я не могу ничего найти. Это довольно легко сделать в C ++, C # и многих других языках, но я не могу найти ничего для прямой C.

По сути, у меня есть файл, и я хочу прочитать этот файл в столбце TEXT или BLOB в моей базе данных MySQL. Это может быть легко достигнуто путем циклического перемещения по файлу и использования последующих вызовов CONCAT() для добавления данных в столбец. Однако я не думаю, что это так элегантно, как решение, и, вероятно, очень подвержено ошибкам.

Я изучил подготовленные операторы, используя mysql_stmt_init() и все привязки и т. Д., Но, похоже, он не принимает указатель FILE для чтения данных в базу данных.

Важно отметить, что я работаю с очень большими файлами, которые не могут быть сохранены в ОЗУ, поэтому чтение всего файла во временную переменную исключено.

Проще говоря: как я могу прочитать файл с диска в базу данных MySQL, используя C? И имейте в виду, должен быть некоторый тип буфера (то есть BUFSIZ из-за размера файлов). Кто-нибудь достиг этого? Является ли это возможным? И я ищу решение, которое работает как с текстовыми, так и с двоичными файлами.

Ответы [ 3 ]

2 голосов
/ 19 февраля 2012

Можно ли использовать LOAD DATA INFILE при вызове mysql_query()?

char statement[STMT_SIZE];
snprintf(statement, STMT_SIZE, "LOAD DATA INFILE '%s' INTO TABLE '%s'",
    filename, tablename);
mysql_query(conn, statement);

См. http://dev.mysql.com/doc/refman/5.6/en/load-data.html и http://dev.mysql.com/doc/refman/5.6/en/mysql-query.html для соответствующих страниц в документах MySQL.

0 голосов
/ 23 февраля 2012

Мне не нравится отвечать на мои собственные вопросы, но я чувствую необходимость в том случае, если кто-то еще ищет решение этой проблемы в будущем.

Если я что-то упустил, мои исследования и тестирование показали, что у меня есть три основных варианта:

  1. Достойное решение: используйте оператор LOAD DATA INFILE для отправки файла
    • плюсы: понадобится только одно утверждение. В отличие от загрузки всего файла в память, вы можете настроить производительность LOAD DATA как на клиенте, так и на сервере, чтобы использовать заданный размер буфера, и вы можете сделать этот буфер намного меньше, что даст вам «лучший» контроль буфера без совершать многочисленные звонки
    • минусы: Прежде всего, файл абсолютно ДОЛЖЕН быть в заданном формате, что может быть трудно сделать с файлами двоичных двоичных объектов. Кроме того, это требует значительного объема работы для настройки и требует большой настройки. По умолчанию клиент будет пытаться загрузить весь файл в память и использовать пространство подкачки для объема файла, который не помещается в память. Здесь очень легко получить ужасную производительность, и каждый раз, когда вы хотите внести изменения, вам нужно перезапустить сервер mysql.
  2. Достойное решение: Иметь буфер (например, char buf[BUFSIZ]) и делать многочисленные запросы с CONCAT() вызовами для обновления содержимого
    • плюсы: использует наименьшее количество памяти и дает программе лучший контроль над тем, сколько памяти используется
    • cons: занимает МНОГО времени обработки, потому что вы делаете многочисленные вызовы mysql, и сервер должен найти данную строку, а затем добавить к ней строку (что занимает время, даже если кэширование)
  3. Худшее решение: Попробуйте загрузить весь файл в память (или как можно больше) и сделать только один INSERT или UPDATE вызов mysql
    • плюсы: ограничивает объем производительности обработки, необходимый клиенту, поскольку только минимальное количество вызовов (предпочтительно один) должно быть буферизовано и выполнено.
    • минусов: занимает тонну памяти. Если у вас есть многочисленные клиенты, выполняющие эти крупные вызовы одновременно, серверу быстро не хватит памяти, и любой выигрыш в производительности очень быстро превратится в потери.

В идеальном мире MySQL реализовал бы функцию, которая позволяла бы буферизовать запросы, что-то вроде буферизации видео: вы открываете соединение MySQL, затем в этом открываете «соединение запроса» и потоковые данные в буферизованных наборах, затем закрыть «запрос соединения»

Однако это НЕ идеальный мир, и в MySQL такого нет. это оставляет нас с тремя вариантами, показанными выше. Я решил придерживаться второго, когда я совершаю многочисленные CONCAT() звонки, потому что у моего текущего сервера достаточно времени для обработки, и я очень ограничен в памяти клиентов. Для моей уникальной ситуации пытаться биться головой о настройке LOAD DATA INFILE не имеет смысла. Однако каждое приложение должно анализировать свою проблему.

Подчеркну, что ни один из них не "идеален" для меня, но вы можете делать лучшее только с тем, что имеете.

Указывает Адаму Лиссу за направление LOAD DATA INFILE.

0 голосов
/ 19 февраля 2012

Вы можете использовать цикл для чтения файла, но вместо использования функции, такой как fgets(), которая читает по одной строке за раз, используйте функцию более низкого уровня, такую ​​как read() или fread(), которая заполнит буфер произвольного размера за раз:

allocate large buffer
open file
while NOT end of file
    fill buffer
    CONCAT to MySQL
close file
release buffer
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...