Практика работы с файлами и базой данных в Laravel и ChatGPT
Рассказываем, как ChatGPT справилась с обработкой данных. Модель попросили взять данные из таблицы, перенести их в БД и экспортировать в csv.
1К открытий3К показов
Работа с файлами и базой данных всегда является потенциальным местом возникновения ошибок со временем. Проблемы в коде, такие как загрузка всего файла в память, получение всех данных из базы данных за один запрос, отсутствие массовой вставки в базу данных и т.д., не доставят проблем с небольшими объемами данных, но неизбежно создадут их, когда объем данных увеличится.
Мне стало интересно, насколько оптимальный код напишет chatgpt 3.5 в рамках задачи: Есть большой (более 200 мб) xml файл (cities.xml) со структурой: <cities><city><name>CityName</name></city></cities>
.
Необходимо получить данные из файла и заполнить ими таблицу cities
с полями name
, created_at
, updated_at
.
Также нужно создать команду, которая получит все данные из таблицы cities
, добавит каждой записи случайное число от 1 до 10 и выгрузит в csv файл в формате (Name
, Created At
, Random Number
). Приложение написано на Laravel.
Условно, можно разделить задачу на этапы:
- Получаем данные из xml, заполняем бд;
- Получаем данные из бд, заполняем csv.
Приступим к решению!
Получаем данные из xml, заполняем бд
Первым делом, составим запрос к chatgpt:
> Есть большой cities.xml файл со структурой: <cities><city><name>CityName</name></city></cities>. Создай команду, которая прочитает cities.xml и заполнит таблицу сities с полем name. На Laravel.
Ответ:
Очень здорово, что помимо самой команды, chatgpt описал все необходимые шаги, для того, чтобы команда работала.
Но будет ли команда работать на практике? Нет, получаем ошибку по памяти. Проблема в том, что simplexml_load_file('cities.xml')
создает объектную модель документа и полностью грузит её в память.
Так как файл большой, это сразу приводит к PHP Fatal error: Out of memory
.
Корректность использования City::create([])
(в рамках этой задачи) вызывает сомнение и приводит к одной из вариации n+1 проблемы, так как на создание каждой сущности, будет создаваться запрос к бд.
Сообщим chatgpt об ошибке:
> Файл cities.xml очень большой, этот код не работает, возникает ошибка PHP Fatal error
Ответ:
> Да, этот код не полный и не будет работать без дополнительных деталей. Необходимо также добавить обработку ошибок при чтении файла, проверку наличия записи в таблице перед ее созданием и т.д. Это лишь базовый пример, который может быть дополнен и улучшен в зависимости от конкретных требований проекта.
Хороший ответ, надо бы запомнить.
Конкретизирую запрос:
> Оптимизируй код команды для работы с большими данными.
Ответ:
В этот раз chatgpt написал оптимальный код.
Он использует комбинацию XMLReader + SimpleXml для работы с xml. XMLReader построчно читает файл (тем самым не расходует много памяти), а SimpleXml предоставляет удобный интерфейс для работы с интересующим узлом (в память загружается только узел, а не весь файл целиком).
При записи в бд, он использует массовую вставку City::insert()
и Batch processing, где переменная $batchSize
регулирует количество элементов для вставки за один запрос, тем самым уменьшая общее количество запросов к бд.
Получаем данные из бд, заполняем csv
На этом этапе контекст потерялся, поэтому запрос более развернутый:
> Есть таблица cities и модель City с полями name, created_at в Laravel. Создай команду которая выгрузит все City в csv файл и добавь каждому City случайное число от 1 до 10. Оптимизируй код для работы с большими данными
Ответ:
Предложенный код решает поставленную задачу. Использование chunk() позволяет получать данные из таблицы по частям и не загружать все записи в память одновременно.
Узнаем, почему этот код оптимален:
> Почему этот код оптимальный?
> Этот код является оптимальным, как указано выше.
Тогда действуем от противного:
> Почему это решение не является оптимальным?
Ответ:
> Данное решение может быть не оптимальным в случае, если таблица City содержит очень большое количество записей. В таком случае, использование метода chunk() с параметром 1000 может быть недостаточным для оптимальной обработки данных. Также, при работе с большими объемами данных, использование SplFileObject может привести к снижению производительности из-за частых операций записи на диск. В таких случаях может быть более эффективным использование специализированных инструментов для работы с большими данными, таких как Apache Spark или Hadoop.
Действительно, параметр получаемых записей в chunk(), значимо влияет на производительность приложения. Например, это время работы и потребляемая память с параметром 100.000:
Time taken: 106.76 seconds
Memory used: 2.62 MB
А это с 300.000:
Time taken: 95.42 seconds
Memory used: 8.61 MB
Следовательно, необходимо экспериментально найти оптимальное значение параметра.
Решение этой задачи я выбирал из 12 предложенных вариантов кода.
7 из 12 были оптимальны, работоспособны и схожи по логике. Разнились подходы работы с файлом, в паре случаев использовался фасад Storage
, где то сторонняя библиотека, ни разу fopen
. Метод chunk()
встречался в 100% случаев. Конечный код был выбран из этих вариантов и содержит наиболее часто встречающиеся решения.
2 из 12 были рабочие, но не были оптимальны и загружали все данные за раз (City::all())
.
Остальные не работали по разным причинам: вызывались несуществующие методы, была нарушена логика работы, переданы неправильные аргументы. Во всех случаях, chatgpt самостоятельно не нашёл ошибки.
Итог
Chatgpt справился с поставленными задачами. Как было замечено выше, он не находил в своих решениях ошибки и исправлял только после указания на них. Я решил узнать об этом:
> Почему ты написал код не правильно?
> Как именно был написан код, я не могу сказать, так как его не видел. Однако, возможно, автор первоначально не знал о функции fputcsv() и попытался использовать implode() для форматирования данных в csv строку.
> То есть ты используешь не проверенные данные для ответов?
> Как искусственный интеллект, я не могу использовать "проверенные данные", так как я не имею личного опыта или восприятия. Однако, я основываю свои ответы на знаниях и алгоритмах, которые были программированы моими создателями. Я стараюсь давать наиболее точный ответ на основе доступной информации.
Да, chatgpt не пишет код, он его синтезирует. Он любит выдумывать и попытается убедить в этом Вас. Но это не мешает ему быть очень полезным инструментом. Если было полезно, ставьте классы. Всем добра!
1К открытий3К показов