X   Сообщение сайта
(Сообщение закроется через 3 секунды)



 

Здравствуйте, гость (

| Вход | Регистрация )

Открыть тему
Тема закрыта
> Обработка большого текстового файла
gaaarfild
gaaarfild
Topic Starter сообщение 15.9.2010, 17:11; Ответить: gaaarfild
Сообщение #1


Есть такая опция, когда пользователи обновляют Базу данных с помощью CVS файла.
Но файлы достаточно большие. 1-2 мегабайта.
Каждая строчка содержит госномер машины, VIN и компанию, которой принадлежит машина, а так же периоды страховки ее.
При загрузке в БД идет сначала проверка, нет ли такого авто уже в БД. Если есть, то его необходимо просто обновить. Если нет, то добавить новую запись.
У меня данная конструкция получается очень сильно громоздкой.
И скрипт есть очень много ресурсов, потому что очень много запросов в БД. Подскажите пожалуйста, как можно максимально оптимизированно обрабатывать файл?

Вот пример CSV файла.
SkID;nomZvl;vidStr;VIN;gosNom;model;dts;dtPo;dtSl
HTN;803р-08АлФ;1;XTA21102020541895;;ВАЗ 2110;2008-7-31;2009-7-30;2008-11-20
HTN;805р-08АлФ;1;X8927851B50BE3893;;БАГЕМ 278510;2008-6-24;2009-6-23;2008-11-20
HTN;806р-08АлФ;1;KLAJF19W1VB201104;Х468РР;DAEWOO ESPERO;2008-8-4;2009-8-3;2008-11-21
HTN;807р-08АлФ;1;XTA21074011442260;Х250РН;ВАЗ 2107;2008-9-2;2009-9-1;2008-11-24
HTN;808р-08АлФ;1;XTA210990T1820120;T006ЕУ;ВАЗ 21099;2008-4-30;2009-4-29;2008-11-24
HTN;809р-08АлФ;1;JMBSNCS3A6U017800;Х606АУ;MITSUBISHI LANCER;2008-5-2;2009-5-1;2008-11-25


Вот код обработки
[php]if($_FILES['usercsv']['tmp_name']!="") {
if($files_class->get_typefile($_FILES['usercsv']['name'])!='csv') {
header('Location: index.php?mod=carbaseedit&do=Add&error=filetypeerror');
}
$che = 1;
do {
$filename = date('d-m-Y_H-i-s').'('.$che.').csv';
//$filename = rand(1000000, 9000000).'.csv';
$che++;
} while (file_exists('uploads/tmp/'.$filename));

if(!copy($_FILES['usercsv']['tmp_name'], 'uploads/tmp/'.$filename)) {
header('Location: index.php?mod=carbaseedit&do=Add&error=uploaderror');
} else {
//setlocale(LC_ALL, 'ru_RU.UTF-8');
$file_size = filesize('uploads/tmp/'.$filename)+100;
$fo = fopen('uploads/tmp/'.$filename, "r");
$row = 1;
//$db->sql_query("TRUNCATE TABLE ".$prefix."_car_rollback");
$records_sum = 0;
$filecont = file_get_contents('uploads/tmp/'.$filename);
while (($line = fgets($fo, $file_size)) !== false) {
if($row!=1) {
$data=explode(';', $line);
// [0] - Код компании
// [1] - Заявление
// [2] - Каско\Осаго
// [3] - VIN
// [4] - Госномер
// [5] - Модель машины
// [6] - Дата С
// [7] - Дата По
// [8] - Дата случая

list($cid) = $db->sql_fetchrow($db->sql_query("SELECT id FROM ".$prefix."_ins_companies WHERE `tid` LIKE '".$data[0]."'"));
$gosnom_sh = str_replace(' ', '', $data[4]);
//$gosnom = iconv('cp1251', 'utf-8//IGNORE', $gosnom);
$gosnom_sh = $texts_class->translit_toeng_repl($gosnom_sh);
$dat_adate = explode('-', $data[8]);
$region = mb_substr($gosnom_sh, 7);
$vin = str_replace(' ', '', $data[3]);
$dat_from = explode('-', $data[6]);
$date_fr = mktime(3,0,0, $dat_from[1], $dat_from[2], $dat_from[0]);
$dat_to = explode('-', $data[7]);
$date_to = mktime(3,0,0, $dat_to[1], $dat_to[2], $dat_to[0]);
$dat_adate = explode('-', $data[8]);
$adate = mktime(3,0,0, $dat_adate[1], $dat_adate[2], $dat_adate[0]);
$result = $db->sql_query("SELECT id FROM ".$prefix."_car WHERE `company`=".$cid." AND `gosnomer`='".$gosnom_sh."' AND `vin`='".$vin."' AND `adate`=".$adate."");
if($db->sql_numrows($result)==0) {
$gosnom_sh = $texts_class->translit_toeng_repl($gosnom_sh);
$result = $db->sql_query("SELECT id FROM ".$prefix."_car WHERE `company`=".$cid." AND `gosnomer`='".$gosnom_sh."' AND `vin`='".$vin."' AND `adate`=".$adate."");
}
//print_r($db->sql_error());
if($db->sql_numrows($result)==0) {
$gosnom_sh = $texts_class->translit_toeng_repl($gosnom_sh);
$result1 = $db->sql_query("INSERT INTO ".$prefix."_car (`gosnomer`, `region`, `model`, `claim`, `company`, `company_code`, `ins_type`, `fr`, `fr_d`, `to`, `to_d`, `adate`, `adate_d`, `vin`, `add_time`, `uinput`) VALUES ('".$gosnom_sh."', '".$regison."', '".mysql_escape_string(str_replace('"', '', trim($data[5])))."', '".mysql_escape_string(trim($data[1]))."', ".$cid.", '".mysql_escape_string(trim($data[0]))."', ".intval($data[2]).", ".$date_fr.", '".mysql_escape_string(trim($data[6]))."', ".$date_to.", '".mysql_escape_string(trim($data[7]))."', ".$adate.", '".mysql_escape_string(trim($data[8]))."', '".$vin."', ".time().", ".intval($_SESSION['user_id']).")");
$newcar_id = $db->sql_nextid($result1);
$db->sql_query("INSERT INTO ".$prefix."_car_rollback (`car_id`, `time`, `company`) VALUES (".$newcar_id.", ".time().", ".intval($_SESSION['company_id']).")");
$db->sql_query("INSERT INTO ".$prefix."_ins_period (`fr`, `to`, `car_id`, `add_time`, `uinput`) VALUES (".$date_fr.", ".$date_to.", ".$newcar_id.", ".time().", ".intval($_SESSION['user_id']).")");
$db->sql_query("INSERT INTO ".$prefix."_accident (`adate`, `car_id`, `add_time`, `uinput`) VALUES (".$adate.", ".$newcar_id.", ".time().", ".intval($_SESSION['user_id']).")");
//print_r($db->sql_error());
} else {
list($sid) = $db->sql_fetchrow($result);
$gosnom_sh = $texts_class->translit_toeng_repl(trim($gosnom_sh));
$db->sql_query("UPDATE ".$prefix."_car SET `gosnomer`='".$gosnom_sh."', `region`='".trim($region)."', `model`='".mysql_escape_string(trim($data[5]))."', `claim`='".mysql_escape_string(trim($data[1]))."', `company`=".$cid.", `company_code`='".mysql_escape_string(trim($data[0]))."', `ins_type`=".intval($data[2]).", `fr`=".$date_fr.", `fr_d`='".mysql_escape_string(trim($data[6]))."', `to`=".$date_to.", `to_d`='".mysql_escape_string(trim($data[7]))."', `adate`=".$adate.", `adate_d`='".mysql_escape_string(trim($data[8]))."', `vin`='".$vin."', `uinput`=".intval($_SESSION['user_id'])." WHERE id=".$sid."");
$result3 = $db->sql_query("SELECT id FROM ".$prefix."_ins_period WHERE `car_id`=".$sid." AND `fr`=".$date_fr." AND `to`=".$date_to."");
if($db->sql_numrows($result3)==0) {
$db->sql_query("INSERT INTO ".$prefix."_ins_period (`fr`, `to`, `car_id`, `add_time`, `uinput`) VALUES (".$date_fr.", ".$date_to.", ".$sid.", ".time().", ".intval($_SESSION['user_id']).")");
}
$result4 = $db->sql_query("SELECT id FROM ".$prefix."_accident WHERE `car_id`=".$sid." AND `adate`=".$adate."");
if($db->sql_numrows($result4)==0) {
$db->sql_query("INSERT INTO ".$prefix."_accident (`adate`, `car_id`, `add_time`, `uinput`) VALUES (".$adate.", ".$newcar_id.", ".time().", ".intval($_SESSION['user_id']).")");
}
//print_r($db->sql_error());
}
}
$records_sum = ($row!=1) ? ++$records_sum : $records_sum;
$row++;

}
//unlink('uploads/tmp/'.$filename);
$db->sql_query("INSERT INTO ".$prefix."_upload_stats (`date`, `company`, `uid`, `filename`, `filesize`, `records`) VALUES (".time().", ".intval($cid).", ".intval($_SESSION['user_id']).", '".$filename."', '".$_FILES['usercsv']['size']."', ".$records_sum.")");
print_r($db->sql_error());
// Логирование начало
$core_class->log_text_db = 'filename: '.mysql_escape_string($_FILES['usercsv']['name']).' -> '.$filename.', filesize: '.intval($file_size).'b';
$core_class->log_text_file = 'filename: '.mysql_escape_string($_FILES['usercsv']['name']).' -> '.$filename.', filesize: '.intval($file_size).'b';
$core_class->log_to_file('carbase_load_csv');
$core_class->log_to_db('carbase_load_csv');
//Логирование конец
header('Location: index.php?mod=carbaseedit&do=Add&error=noerror');
}
} else {
header('Location: index.php?mod=carbaseedit&do=Add&error=nofile');
}[/php]
0
Вернуться в начало страницы
 
Ответить с цитированием данного сообщения
ZiTosS
ZiTosS
сообщение 15.9.2010, 22:24; Ответить: ZiTosS
Сообщение #2


gaaarfild,
1) Не CVS а CSV - (от англ. Comma Separated Values — значения, разделённые запятыми) — это текстовый формат, предназначенный для представления табличных данных.
2) Я бы сделал так (если позволяет память в PHP), все бы даннные из файлов считал бы в массивы, как, я думаю объяснять не стоит.
3) Далее сразу бы прошёлся по базе с поиском уже существующих и удалил бы из массива не нужные данные. Тут без кучи запросов не обойтись
4) А вот со вставкой можно оптимизировать. Вообще за один запрос можно вставить кучу записей, для этого просто нужно перечислять их через запятую:
INSERT INTO table VALUES (данные1), (данные2), ... , (данныеN);

Тут тебе поможет функция implode. Как видишь, тут один запрос и много записей за раз.
5) Так можно сформировать для всех INSERT, вот только я не помню, есть ли в MySQL ограничение на количество вставляемых записей за раз... Ну тут можно и разбить массив, по частям вставлять.
Вернуться в начало страницы
 
Ответить с цитированием данного сообщения
gaaarfild
gaaarfild
Topic Starter сообщение 15.9.2010, 23:02; Ответить: gaaarfild
Сообщение #3


Проблема в том, что сервер вроде VPS c 2 гигами оперативы и нормальным процессором. Но при загрузке файла более 700 кб вешается все напрочь.
Вернуться в начало страницы
 
Ответить с цитированием данного сообщения
ZiTosS
ZiTosS
сообщение 15.9.2010, 23:31; Ответить: ZiTosS
Сообщение #4


gaaarfild, Нужно посмотреть сколько памяти выделяется PHP-процессу:
http://www.php.su/functions/?memory-get-usage

Пойми, если ты читаешь сразу весь файл, то он пытается занестись полностью в память выделенную процессу, если она мала, то это очень плохо.
Могу предложить читать файл построчно или посимвольно, намного быстрее. Тут главное чтобы памяти хватило для хранения данных.
Вернуться в начало страницы
 
Ответить с цитированием данного сообщения
elagin1987_mw
elagin1987_mw
сообщение 4.10.2010, 4:27; Ответить: elagin1987_mw
Сообщение #5


Вот этой функцией можно читать большие файлы, проверял на 2 гиговом файле
fread


Замечание модератора:
Эта тема была закрыта автоматически ввиду отсутствия активности в ней на протяжении 100+ дней.
Если Вы считаете ее актуальной и хотите оставить сообщение, то воспользуйтесь кнопкой
или обратитесь к любому из модераторов.
Вернуться в начало страницы
 
Ответить с цитированием данного сообщения
Открыть тему
Тема закрыта
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0


Свернуть

> Похожие темы

  Тема Ответов Автор Просмотров Последний ответ
Открытая тема (нет новых ответов) Тема имеет прикрепленные файлыpocket-exchange.com - обмен электронных валют. Низкие курсы! Быстрая обработка заявок!
8 pocket_exchange 9366 12.8.2022, 15:30
автор: pocket_exchange
Открытая тема (нет новых ответов) Сотрудничество и качественная обработка трафика
4 BNRKmaster 893 12.6.2021, 13:02
автор: NormanSky
Открытая тема (нет новых ответов) Нужна обработка фото в стиле GTA
4 Yoga 1867 4.1.2021, 19:28
автор: essed
Открытая тема (нет новых ответов) Парсинг, наполнение\обработка, верстка и перенос сайтов, программирование на php
Спаршу\обработаю\залью контент для ваших сайтов\магазинов
1 mazdada 1075 26.12.2020, 21:46
автор: Mukis
Открытая тема (нет новых ответов) Вакансия: Обработка заявок в GoGetLinks и Miralinks
5 Monarx 2208 26.5.2020, 16:28
автор: mark2013


 



RSS Текстовая версия Сейчас: 25.4.2024, 7:53
Дизайн