Массовая вставка MySql из огромного массива: вопрос оптимизации

Меня попросили выбрать лучший вариант из трех с точки зрения оптимизации ресурсов.
Предположим, у меня есть большой файл Excel с тысячами записей, и мне нужно извлечь эти данные и вставить их в базу данных. . 3 варианта:

  1. Загружать все в многомерный массив и вставлять все одним сложным запросом;
  2. Загрузите все в многомерный массив, затем переберите каждую строку Excel и выполните простой запрос на вставку.
  3. Внутри цикла прочитайте каждую строку Excel, поместите ее в массив, а затем выполните простой запрос на вставку в БД.

Это для теста на собеседовании (я назвал это домашним заданием, не уверен, что это правильно); Я ненадолго задумался:

  • Случай 1: я могу рискнуть ошибкой *out_of_memory* (конечно, в зависимости от машины), но это решение выполняет меньше запросов к базе данных. Два недостатка — огромный объем памяти, который нужно выделить как для массива, так и для базы данных. Я знаю, что могу преобразовать Excel в CSV, но здесь это не вариант. Я бы выбрал большой массив и массовую вставку, но боюсь, что это будет сложно для базы данных.
  • Случай 2: я могу рискнуть ошибкой *out_of_memory* при загрузке в массив, но не для второй задачи. Тем не менее, выполнение тысяч запросов может сказаться на производительности базы данных, и этот запрос, скорее всего, будет кандидатом на оптимизацию.
  • Вариант 3. По-прежнему существует цикл с тысячами записей (что также занимает много памяти...) и по-прежнему выполняются тысячи запросов (которые поражают базу данных).

Итак, я на самом деле выбрал первый ответ, и мне пришлось немного подумать, прежде чем сделать это.

И это было НЕПРАВИЛЬНО. И я на самом деле не знаю, какой из трех был правильным.

Может ли кто-нибудь помочь мне в этом? Так ли плох этот ответ? Я думал, что тысячи запросов на вставку будут «плохими», но, похоже, я совершенно не прав.

РЕДАКТИРОВАТЬ
Уточнение: мой вопрос не о том, какая оптимизация является лучшей абсолютно, а о том, какая из трех, которые я представил; поэтому я не рассматриваю другие альтернативы, а просто объясняю, почему я был неправ и какой ответ аргументированно является лучшим.


person Damien Pirsy    schedule 11.07.2011    source источник
comment
Спасибо за исправление тега   -  person Damien Pirsy    schedule 12.07.2011
comment
Игра в адвоката дьявола. Разве вы не можете сохранить электронную таблицу в формате CSV и использовать MySQL LOAD DATA LOCAL INFILE для ее импорта? Зачем использовать PHP?   -  person Michael Berkowski    schedule 12.07.2011
comment
@Майкл, я думаю, Дэмиену пришлось выбирать из трех вариантов.   -  person Candide    schedule 12.07.2011
comment
@Michael Это было короткое тестовое онлайн-собеседование при приеме на работу, мне просто нужно было выбрать один из 3 ответов на каждый вопрос. Я надеюсь, что смогу обсудить их во время настоящего интервью и объяснить свои причины.   -  person Damien Pirsy    schedule 12.07.2011
comment
@Roland @Damien Да, я обещаю полностью читать вопросы в будущем. Извини :(   -  person Michael Berkowski    schedule 12.07.2011


Ответы (3)


С одной стороны, это похоже на вопрос с подвохом. Разумный ответ — использовать утилиту массового импорта, такую ​​как mysqlimport в MySQL или BULK INSERT ... FROM [data_file] в SQL Server. С другой стороны, эти утилиты, по сути, выполняют один из трех вышеперечисленных вариантов (хотя, предположительно, высокооптимизированным образом).

Дело в том, что при ответе на них вы должны учитывать весь вопрос. «Лучший вариант с точки зрения использования ресурсов» — это случай 3, учитывая, что использование памяти будет довольно низким и что большинство платформ баз данных в любом случае предназначены для обработки метрического количества запросов в секунду.

person Justin ᚅᚔᚈᚄᚒᚔ    schedule 11.07.2011
comment
возможно, в реальном приложении я бы тоже выбрал первый, с LOAD INFILE или BULK INSERT и CSV-преобразованием файла Excel. Но в этом сценарии эта опция была недоступна ... Я тоже подозревал номер 3), но я думал, что все эти циклы будут ресурсоемкими, кажется, я совершенно ошибаюсь в этом - person Damien Pirsy; 12.07.2011
comment
Зацикливание файла должно произойти в любом случае, но с вариантом 3 вы обрабатываете данные по мере их извлечения, отбрасываете их и идете дальше. Первые два требуют, чтобы вы сохранили данные и обработали их позже (по сути, два цикла вместо одного). - person Justin ᚅᚔᚈᚄᚒᚔ; 12.07.2011

"Неправильно" кажется неправильным ответом.

Существует ряд компромиссов, и «правильный» ответ зависит от факторов, которые вы не указали, таких как: 1) Это производственная база данных? 2) Сайт онлайн, когда вы вводите эти данные? 3) Это нормально, если строка 1 вставлена ​​и видна для публики, а строка 10 985 - нет? 4) Пишут ли другие в стол, пока вы?

Предполагая, что ответ на все эти вопросы положительный, я, вероятно, буду читать и вставлять строку за раз. Первые два заблокируют вашу таблицу, чтобы никто другой не смог получить к ней доступ. С опцией 3 вы даже можете измерить скорость вставки.

person Ray Baxter    schedule 11.07.2011
comment
У меня такой информации нет, тест был сформулирован примерно так, как я выложил (только на другом языке ;)) - person Damien Pirsy; 12.07.2011
comment
+1 Невозможно ответить, не зная, активно ли используется база данных. С одной стороны, вы можете столкнуться с проблемами согласованности. С другой стороны, выполнение одного массивного запроса может заблокировать БД. - person Michael Mior; 12.07.2011

Я думаю, что путь PHP предполагает случай 3, потому что вы минимизируете объем используемой памяти. Это медленно, но уменьшает объем памяти, который занимает каждая операция. Загрузка всего этого в один большой многомерный массив и выполнение сложной вставки требует гораздо больше ресурсов, и ускорение не намного лучше. Вопрос предполагает, что это длительная задача, поэтому, возможно, это вас и сбило с толку.

Тот, кто написал это, похоже, не учел, что операции вставки являются дорогостоящими для загрузки данных и не предназначены для использования, когда у вас есть много данных для загрузки.

person Candide    schedule 11.07.2011