Импорт и обработка текстового файла в MySQL

Я работаю над исследовательским проектом, который требует от меня обработки больших файлов csv (~ 2-5 ГБ) с 500 000 записей. Эти файлы содержат информацию о государственных контрактах (из USASpending.gov ). До сих пор я использовал скрипты PHP или Python для атаки файлов по строкам, их анализа, а затем вставлял информацию в соответствующие таблицы. Разбор умеренно сложный. Для каждой записи скрипт проверяет, находится ли имя объекта уже в базе данных (используя комбинацию соответствия строк и регулярных выражений); если это не так, он сначала добавляет объект в таблицу сущностей, а затем переходит к анализу остальной части записи и вставляет информацию в соответствующие таблицы. Список организаций составляет более 100 000 человек.

Вот основные функции (часть класса), которые пытаются сопоставить каждую запись с любыми существующими объектами:

private function _getOrg($data) { // if name of organization is null, skip it if($data[44] == '') return null; // use each of the possible names to check if organization exists $names = array($data[44],$data[45],$data[46],$data[47]); // cycle through the names foreach($names as $name) { // check to see if there is actually an entry here if($name != '') { if(($org_id = $this->_parseOrg($name)) != null) { $this->update_org_meta($org_id,$data); // updates some information of existing entity based on record return $org_id; } } } return $this->_addOrg($data); } private function _parseOrg($name) { // check to see if it matches any org names // db class function, performs simple "like" match $this->db->where('org_name',$name,'like'); $result = $this->db->get('orgs'); if(mysql_num_rows($result) == 1) { $row = mysql_fetch_object($result); return $row->org_id; } // check to see if matches any org aliases $this->db->where('org_alias_name',$name,'like'); $result = $this->db->get('orgs_aliases'); if(mysql_num_rows($result) == 1) { $row = mysql_fetch_object($result); return $row->org_id; } return null; // no matches, have to add new entity } 

Функция _addOrg вставляет информацию нового объекта в db, где, надеюсь, он будет соответствовать последующим записям.

Вот проблема: я могу получить только эти скрипты для анализа около 10 000 записей в час, что, учитывая размер, означает несколько твердых дней для каждого файла. Способ структурирования моего db требует обновления нескольких разных таблиц для каждой записи, поскольку я собираю несколько внешних наборов данных. Таким образом, каждая запись обновляет две таблицы, и каждый новый объект обновляет три таблицы. Я беспокоюсь, что это добавляет слишком много времени ожидания между сервером MySQL и моим скриптом.

Вот мой вопрос: есть ли способ импортировать текстовый файл во временную таблицу MySQL, а затем использовать внутренние функции MySQL (или PHP / Python wrapper) для ускорения обработки?

Я запускаю это на своей Mac OS 10.6 с локальным сервером MySQL.

Related of "Импорт и обработка текстового файла в MySQL"

загрузите файл во временную / промежуточную таблицу, используя данные загрузки данных, а затем используйте хранимую процедуру для обработки данных – не должно занимать больше 1-2 минут, чтобы полностью загрузить и обработать данные.

вы также можете найти некоторые мои другие ответы, представляющие интерес:

Оптимальные настройки MySQL для запросов, которые предоставляют большие объемы данных?

MySQL и NoSQL: помогите выбрать правильный

Как избежать использования временных запросов во многих случаях?

60 миллионов записей, выберите записи за определенный месяц. Как оптимизировать базу данных?

Интересная презентация:

http://www.mysqlperformanceblog.com/2011/03/18/video-the-innodb-storage-engine-for-mysql/

пример кода (может быть вам полезен)

 truncate table staging; start transaction; load data infile 'your_data.dat' into table staging fields terminated by ',' optionally enclosed by '"' lines terminated by '\n' ( org_name ... ) set org_name = nullif(org_name,''); commit; drop procedure if exists process_staging_data; delimiter # create procedure process_staging_data() begin insert ignore into organisations (org_name) select distinct org_name from staging; update... etc.. -- or use a cursor if you have to ?? end# delimiter ; call process_staging_data(); 

Надеюсь это поможет

Похоже, вы больше всего выиграете от настройки ваших SQL-запросов, вероятно, именно там, где ваш скрипт проводит больше всего времени. Я не знаю, как работает клиент PHP MySQL, но MySQLdb для Python довольно быстр. Выполняя наивные тестовые тесты, я могу легко поддерживать вставки / выборки 10 к / сек на одном из моих старых четырехъядерных процессоров. Вместо того, чтобы делать один SELECT за другим, чтобы проверить, существует ли организация, использование REGEXP для проверки их всех одновременно может быть более эффективным (обсуждаемый здесь: MySQL LIKE IN ()? ). MySQLdb позволяет использовать executemany() для одновременного выполнения нескольких вставок, вы можете почти наверняка использовать это в своих интересах, возможно, ваш PHP-клиент позволяет вам делать то же самое?

Другое дело, что с Python вы можете использовать multiprocessing и попробовать как можно больше распараллеливать. У PyMOTW есть хорошая статья о многопроцессорности .