[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Импорт .xls с большим количеством строк, PHPExcel
Страницы: 1, 2
te6a
Цитата (Игорь_Vasinsky @ 25.05.2017 - 08:33)
ибо нефиг запросы в цикле херачить, когда есть multi query

Подскажите пожалуйста, как это реализовать?
Желательно, чтобы не пришлось сильно код кромсать....

Или хотя бы как реализовать апдейт проще, могу файл отделить инсерты от апдейтов и загружать отдельно, хоть так бы намного быстрее вышло.
te6a
Служба поддержки сервера проанализировала ошибку, сказали таймаут выполнения скрипта, 300 сек, обещали увеличить вдвое, пока результата нет.
AllesKlar
Цитата (te6a @ 25.05.2017 - 15:03)
Служба поддержки сервера проанализировала ошибку, сказали таймаут выполнения скрипта, 300 сек, обещали увеличить вдвое, пока результата нет.

Это плохой выход.
Вернее, вообще не выход.
Придет файл с 20К строками, опять в суппорт звонить?

Вариантов уже кучу описали.
Делать мульти-запрос
update...; update...; update...; update...;
или
update when ... then ...
тоже не самое верное решение, потому что сервер БД однажды может сказать: Иди ты нафиг с такими запросами
Цитата (AllesKlar @ 24.05.2017 - 21:58)
Напрмер, мне серевер БД иногда говорит, что не может выделит кеш под запрос размером 26 мб.


Поэтому, как уже сказали, либо временная таблица, либо сохраняешь в csv а потом приходит демон и уже работает столько времени, сколько ему угодно (на cli нет таймаута)

В любом случае, у тебя не получится сделать за один вызов скрипта веб-сервера.



_____________
[продано копирайтерам]
te6a
Такое увеличение времени не спасет, тем более время до ошибки по-прежнему до 4 минут.

Честно говоря в PHP можно сказать 0, дорабатывал сам немного, изменял, но на основании только терминов такое не осилю, если можете как-то в примерах или ткнуть носом где по такому случаю почитать, буду признателен.
Мне хотя бы тыщ по 3, было б достаточно.
sergeiss
Цитата (te6a @ 25.05.2017 - 18:02)
Мне хотя бы тыщ по 3, было б достаточно.

Тебе уже 3 тыщи раз сказали, что надо сделать, чтобы сделать ПРАВИЛЬНО... Ну, например, цитирую:
Цитата (AllesKlar @ 25.05.2017 - 17:26)
Поэтому, как уже сказали, либо временная таблица, либо сохраняешь в csv а потом приходит демон и уже работает столько времени, сколько ему угодно (на cli нет таймаута)


Тему закрыл. Автор пусть подумает о том, не как ему его идею довести до абсурда, а как сделать нормально. Если соберётся делать по-нормальному, то пусть создает об этом новую тему - уже с наработками какими-нибудь. В какую сторону двигаться, ему тут идей накидали.

_____________
* Хэлп по PHP
* Описалово по JavaScript
* Хэлп и СУБД для PostgreSQL

* Обучаю PHP, JS, вёрстке. Интерактивно и качественно. За разумные деньги.

* "накапливаю умение телепатии" (С) и "гуглю за ваш счет" (С)

user posted image
sergeiss
По просьбе ТС тема открыта. Только мне кажется, что он всё равно хочет "свою" идею добивать, не слушая советов...

Для ТС: почитай про "INSERT .... ON DUPLICATE KEY UPDATE ...." (гуглится за 1 минуту) и не занимайся фигнёй. Заодно сделаешь индексы на нужные поля smile.gif
Делаешь отдельную таблицу, льёшь в неё посредством LOAD DATA INFILE, в триггере вставки перехватываешь данные и вставляешь уже в правильную таблицу. Как - я написал в предыдущем абзаце.

_____________
* Хэлп по PHP
* Описалово по JavaScript
* Хэлп и СУБД для PostgreSQL

* Обучаю PHP, JS, вёрстке. Интерактивно и качественно. За разумные деньги.

* "накапливаю умение телепатии" (С) и "гуглю за ваш счет" (С)

user posted image
te6a
Спасибо!
Хочется не просто получить результат, а понять и разобраться (тем более никто готовый вариант не предоставит)
Вы конечно правы в решении глобальной проблемы, но я пока не понял что именно приводит к этой проблеме. Если пойму что приводит к глобальной проблеме, возможно достаточно будет простой оптимизации.
На данный момент:
Саппорт ответил, что не может разобраться в чем именно проблема, в нехватке памяти или времени.
Время выполнения скрипта на сервере увеличили до 10 мин., "крах" происходит всегда примерно через 3мин45сек , если краха нет, данные могут загружаться и дольше.
По памяти здесь отписали, что должно хватать на такую процедуру.
Также "крах" происходит именно при UPDATE (при инсерте грузится быстро, достаточно) ,по логике это и понятно, приходится каждую строку из Эксель сравнивать со всей базой 60000 позиций.
Раз дело не в коде и его параметрах, я так понимаю, есть еще параметры базы, нашел параметр wait_timeout, он как раз примерно равен времени до краха 240 сек.

В остальном спасибо за подсказки, гуглю, разбираюсь.
Особенная благодарность Kusss за помощь и подсказки.
te6a
Добрый день!
Вопрос решен, огромное спасибо в решении проблемы Kusss , измененный ниже скрипт его идея:

Мой скрипт

  <?php


function
importAction () {

if ($_POST) {

// Таблица
$table = '`catalog_test`';
// коннектим функцию
require_once ADMIN_PATH.'/plagin/excel2/reader.php';
// ExcelFile($filename, $encoding);
$data = new Spreadsheet_Excel_Reader();
// Set output Encoding.
$data->setOutputEncoding('UTF8');
$data->setUTFEncoder('mb');
$data->read($_FILES['file1']['tmp_name']);
error_reporting(E_ALL ^ E_NOTICE);

$lines = array();
$artikul = array();
$artikul2 = array();
foreach ( $data->sheets[0]['cells'] AS $key=>$value) {
if ($key == 1)
continue;

// каждая линия
$lines[$key] = array(
'artikul' => $value[1],
'name' => $value[2],
'sklad' => $value[3],
'cost' => $value[4],
'id_parent' => $value[8],
'brand' => $value[11],
'text_short' => $value[12],
'artikb' => $value[13],
);


// Все арктиклы
$artikul[] = "'".$value[13]."'";
$artikul2[$key] = $value[13];
}

$update = array();
// Запрашиваем артикул
$_sql="
SELECT
id, artikb
FROM

$table
WHERE
`artikb` IN ("
.implode(',', $artikul).")
"
;
$result = mysql_query($_sql);
if (mysql_num_rows($result) > 0) {
while($value = mysql_fetch_assoc($result) ) {
// ключ массива $lines
//print_r($value);

$key = array_search($value['artikb'], $artikul2);
// обновить эти строки
$update[] = array (
'artikb'=> $value['artikb'],
'sklad' => $lines[$key]['sklad'],
'cost' => $lines[$key]['cost'],
);

// Все что нужно обновить, удаляем из массива
unset( $lines[$key] );
}
}

$max = 1000;
if (count($update)){
for($i=0;$i <= count($update); $i += $max) {
$up1 = '';
$up2 = '';
$art_array = array();
for ($j=$i;$j < $i+$max; $j++) {
if (!isset($update[$j]))
continue;
$value = $this->mysql_real_escape_array($update[$j]);
$up1 .= "WHEN '".$value['artikb']."' THEN '".$value['sklad']."' ";
$up2 .= "WHEN '".$value['artikb']."' THEN '".$value['cost']."' ";
$art_array[] = " '".$value['artikb']."' ";
}

if (!empty($up1)) {
$up = "UPDATE $table SET ";
$up .= " sklad = CASE `artikb` ". $up1;
$up .= " END ,";
$up .= " cost = CASE `artikb` ". $up2;
$up .= " END ";
$up .= " WHERE `artikb` IN ( ".implode(',', $art_array)." )";
mysql_query($up) or die( '<br>Error UPDATE Mysql:'.mysql_error() );
echo '<br>Update='.count($art_array);
}

}
}

if (count($lines)){
$i = 0;
$lines = $this->mysql_real_escape_array($lines);
$_POST = $this->mysql_real_escape_array($_POST);

foreach ($lines AS $value) {
$i++;
$add[] = "(
'"
.$value['artikul']."',
'"
.$value['name']."',
'"
.$value['cost']."',
'"
.$value['id_parent']."',
'"
.$_POST['type_import2']."',
NOW(),
'"
.$value['sklad']."',
'"
.$_POST['type_import4']."',
'"
.$value['brand']."',
'"
.$value['text_short']."',
'"
.$value['artikb']."'
)"
;
if ($i/$max==intval($i/$max)) {
$this->add_mysql_count($table, $add);
$add = array();
}

}

if (count($add)){
$this->add_mysql_count($table, $add);
}
}

}


return system::show_tpl(
array(
'msg'=>$this->msg,
'select'=>dbh::get_catolog_tree(),
'tpl_folder'=>$this->tpl_folder
),$this->tpl_folder.'/import.php');
}

// Функция добавления части массива
private function add_mysql_count($table, $add){
$sql = "
INSERT INTO

$table
(`artikul`, `name`, `cost`, `id_parent`, `status`, `created_at`, `sklad`, `supplier`, `brand`, `text_short`, `artikb`)
VALUES
"
. implode(',', $add) ."
"
;
mysql_query($sql) or die( '<br>Error ADD Mysql:'.mysql_error() );
echo '<br>Insert='.count($add);

}

?>

Время на загрузку сильно изменилось и измеряется теперь секундами.
Память больше используется при парсинге Экселя и зависит больше от размера самого файла, на загрузку (апдейт и инсерт) уходит мало памяти, плюс сделали разбивку загрузки по 1000 строк, что еще уменьшило использование оперативки.
Парсер Эксель не из библиотеки PHPExcel, из библиотеки оказался медленнее почему-то.
Еще раз благодарю Kusss за отзывчивость и помощь!
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.