Поэтому у меня есть эта таблица:
mysql> DESCRIBE table; +-------+------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------+------------------+------+-----+---------+----------------+ | id | int(15) unsigned | NO | PRI | NULL | auto_increment | | unid | char(9) | NO | UNI | NULL | | | rs | varchar(255) | NO | | NULL | | +-------+------------------+------+-----+---------+----------------+ 3 rows in set (0.00 sec)
Что содержит миллионы строк:
mysql> SELECT COUNT(1) FROM table; +----------+ | COUNT(1) | +----------+ | 9435361 | +----------+ 1 row in set (0.00 sec)
Я хочу экспортировать все строки в .csv
файл (я использую Symfony2.6
). Этот файл предназначен для хранения на сервере (не загружен), а затем, прочитанного PHP.
1-я попытка
Я попытался сделать огромный запрос, чтобы выбрать все сразу ( в соответствии с этим сообщением в блоге ), но это, несмотря на использование ->iterate()
, привело к Allowed memory size of 1073741824 bytes exhausted
после запуска за ~ 9 секунд.
ini_set('memory_limit', '1024M'); ini_set('max_execution_time', -1); $results = $em ->getRepository('MyBundle:Entity') ->createQueryBuilder('e') ->getQuery() ->iterate(); $handle = fopen('/path/to/csv/file/', 'w'); while (false !== ($row = $results->next())) { fputcsv($handle, $row[0]->toArray()); $em->detach($row[0]); } fclose($handle);
Вторая попытка
Я получил общее количество строк, а затем сделал цикл для того, чтобы одно и то же число запросов получало строки по одному. Но после того, как написано ~ 260 тыс. Строк в .csv
файл, у PHP закончилась нехватка памяти и выдается такая же ошибка, как указано выше: Allowed memory size of 1073741824 bytes exhausted
.
ini_set('memory_limit', '1024M'); ini_set('max_execution_time', -1); $total = (int) $em ->getRepository('MyBundle:Entity') ->countAll(); $csv = '/path/to/csv/file'; $handle = fopen($csv, 'w'); for($i = 1; $i < $total; $i++) { $entity = $em->getRepository('MyBundle:Entity')->findOneById($i); fputcsv($handle, $entity->toArray()); $em->detach($entity); } fclose($handle);
3-я попытка
Я подумал об использовании функции exec()
для запуска командной строки MySQL, которая будет экспортировать таблицу. Однако моему менеджеру, похоже, не нравится этот вариант.
Так что я обманываю себя, думая, что демпинг ~ 9,5M строк с использованием PHP в .csv
файл даже возможен? Есть ли другой способ, о котором я еще не знаю?
Спасибо за вашу помощь в этом.
Вместо того, чтобы пытаться построить дерево объектов, вы можете прямо попытаться выбрать результат в файл: http://dev.mysql.com/doc/refman/5.7/en/select.html
Что-то вроде
SELECT * INTO OUTFILE "c:/temp/mycsv.csv" FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY "\n" FROM theTable;
Это должно оставить работу до mysql и обойти ограничения любой памяти php.
Как отметил venca: в этом случае пользователю, под которым вы используете службу mysql, необходимо написать разрешения для соответствующего каталога.