Эффективная обработка данных в оперативной памяти за счет использования коллекции "соответствие"




Принцип обмена данными из 1С с сайтом (на MySQL) и выдачи (публикации) этих данных по запросу.
PHP-Скрипт автоматической загрузки данных из файла данных в формате CSV в базу данных сайта работающего на WordPress.

В продолжение моей темы: 1С:Альфа-Авто Автосалон Автосервис: обмен с сайтом.
С помощью данного скрипта можно загружать в автоматическом режиме, по расписанию, данные сервисных книжек (ремонтов авто) из 1С:Альфа-Авто Автосалон Автосервис.
Также можно загружать данные в ручном режиме: для этого делается скрытая страница, где размещается специальная кнопка.
Комментарии размещенные внутри скрипта разъяснят логику и порядок действия.
Комментарии с "/////    echo" использовались для отладки.
Дополнительно создана таблица для журналирования результатов загрузки данных.
Скрипт включает в себя защиту от SQL инъекций (думаю безопасность соблюдена в полной мере).
В кратце:
1. Пишется скрипт, который запускает этот.
2. Создается регламентное задание в WordPress, по которому запускается скрипт из п.1. 
3. Этот скрипт осуществляет проверку на существование файла обмена в папке.
4. Если данные не новые, загрузка не производится.
5. Если данные новые, очищается таблица сервисных книжек.
6. Загружаются новые данные.

Собственно сам скрипт:

<?php // Полная загрузка сервисных книжек, создан 2025-01-05 12:44:55

global $wpdb2;
global $failure;
global $file_hist;

/////  echo '<H2><b>Старт загрузки</b></H2><br>';

$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
/////   echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}

$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
/////   echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}

/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
/////   echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
/////    echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist);   ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7];    ////получаем размер файла
$m_mtime_file=$masiv_data_file[9];   ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file

/////   echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
/////   echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
/////   echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);

if ($results)
{   foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));

////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
/////   echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
/////   echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}

////загружаем данные
$table='vin_history';         // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация     // (путь от корня web-сервера)
$delim=';';          // Разделитель полей в CSV файле
$enclosed='"';      // Кавычки для содержимого полей
$escaped='\

40 Comments

  1. cool.vlad4

    😀 молодчина, уважаю, знания в массы!

    Reply
  2. hogik

    (0)

    «…есть место настоящему программированию — кодингу»(с)

    «Кодирование является лишь частью программирования, наряду с анализом, проектированием, компиляцией, тестированием и отладкой, сопровождением. В узких кругах кодирование также может называться «кодинг» (англ. coding).»(с)

    http://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%B4%D0%B8%D0%BD%D0%B3

    Reply
  3. Ish_2

    Отлично.

    Гораздо приятнее общаться по такому поводу.

    Замечание 1.

    Нужно поправить в теме.

    Прелесть соответствия именно в том , что проверка перед присвоением не нужна.

    Вместо

             Соотв =  Новый Соответствие;
    Если Соотв[1]= НеОпределено Тогда
    Соотв.Вставить(1,0);
    КонецЕсли;

    Мы пишем :

     Соотв =  Новый Соответствие;
    Соотв[1]=0;

    Другими словами, в последнем примере если не найден ключ , то автоматически вставляется в соответствие новая пара ключ, значение.

    Замечание 2.

    Эффективное использование Соответствие в Вашей обработке графа стало для меня неожиданностью.

    Ваша обработка даже при облегченном контроле зацикливания, неучитывающем «глубокие» кольца,

    должна была проиграть не в 3 раза в SQL-варианте , а в 10-15 раз, если бы использовалась таблица значений.

    Другими словами, если бы не соответствие Ваш алгоритм бы просто «рухнул».

    Сколько же проиграет Ваш вариант при полноценном , неурезанном функционале осталось загадкой.

    Reply
  4. ildarovich

    (2) Не спорю.

    Я использовал здешнее понимание «кодинга» не как кодирование, то есть перевод алгоритма в конструкции языка, а как определение процедурного подхода к программированию, когда требуется определять последовательность вычислений. В отличии от декларативного — «запросного» подхода, против которого я ничего не имею (Пролог — один из моих любимых языков).

    Reply
  5. ildarovich

    (3) С замечанием 1 согласен — уже поправил в статье.

    Reply
  6. ildarovich

    (3) С замечанием 2 не согласен категорически.

    Есть анекдот: «Звонок: Шеф! Будьте осторожнее! — В вашем районе один ненормальный едет по встречке! Ответ шефа: Да какой один! — Их тут сотни!»

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

    По крайней мере четыре человека в Вашей теме считают по-другому: «абсолютно полный контроль зацикливания есть простое перечисление всех дуг, приводящих к зацикливанию».

    Число циклических путей может быть близко к бесконечности. Число ошибочных дуг мало. Их перечисление практически не скажется на быстродействие моей обработки разузлования и других «процедурных» методов, которые на практике в сотни и тысячи раз быстрее Вашего запроса. Все разными словами и разными способами (только на баяне не играли) пытались Вас в этом убедить. Станьте на минутку не писателем, а читателем — ознакомьтесь с нашими доводами! Может быть, наконец, поймете?

    Reply
  7. Ish_2

    (6) Для выяснения спорных вопросов и нужно тестирование. Оно состоялось. Результаты Вы знаете.

    Жаль, что до конца мы не выяснили этот вопрос.

    Reply
  8. Sk0rp

    ИМХО, достаточно было просто написать, что это hash-map

    Reply
  9. Русский

    Поменьше увлекайтесь коллекциями значений! А то уже надоело плеваться при виде кода, в котором данные самым апендицитным образом прогоняются через кучу коллекций значений, вместо того, чтобы грамотно быть извлеченными из ИБ, и воспользоваться универсальными способами(типа ЗаполнитьЗначенияСвойств()).

    P. S. в 8.2 самой частоиспользуемой универсальной коллекцией должна быть структура.

    P. P. S. соответствие, наряду с быстродействием при извлечении данных из нее, проигрывает в быстродействии записи данных в оную по сравнению с той же структурой… Проще говоря, если есть некий массив данных, для которого требуется многократный поиск по значению, то стоит пользоваться соответствием, а если не требуется такого интенсивного, многократного поиска, то лучше воспользоваться другими коллекциями…

    Reply
  10. ildarovich

    (9) Вы сделали правильные выводы. Крайностей быть не должно. Я тоже не призываю использовать соответствие вместо структуры. В приведенном коде, например, структура замечательно подошла для передачи параметров в функцию «ПолучитьСлово()».

    Что касается «ЗаполнитьЗначенияСвойств()». — Исключительно удобная вещь! Постоянно применяю эту конструкцию. Более того, в исходном варианте статьи был «Вариант 4» для таблицы значений, записанный так, как я обычно делаю:

    Строка = ТаблицаЗначений.Найти(Элемент, «Ключ»);
    Если Строка = Неопределено Тогда ЗаполнитьЗначенияСвойств(ТаблицаЗначений.Добавить(), Новый Структура(«Ключ, Значение», Элемент, 1))
    Иначе Строка.Значение = Строка.Значение + 1
    КонецЕсли

    В окончательном варианте этот пример, как более медленный (хоть и более красивый), я убрал. Он остался в прилагаемом отчете «БыстродействиеКоллекций»

    Reply
  11. Ish_2

    Проверяя высказывание (9), в задаче заполнения графа интересно было бы сравнение использования Структуры и Соответствия.

    Если в БП 1.6 (2.0) поле код уникально в справочнике ,

    то вполне можно допустить использование этотого символьного иденификатора для обозначения элемента справочника.

    И тогда какой выигрыш дало бы использование Структуры вместо Соответствия ?

    Reply
  12. Арчибальд
    Сам узнал о сравнительной эффективности коллекций из статьи Сергея Осипова

    Это то, о чем я подумал, или, пардон, я неправ? 😮

    Reply
  13. artbear

    (9) Структура не так универсальна, как соответствие 🙁

    Ключом структуры не может быть любая строка, а только строка, подходящая для использования в качестве идентификаторе в языке 1С.

    т.е. нельзя написать Структура.Вставить(«ид с пробелом», 1) или Структура.Вставить(«1253», 1) и т.п.

    в итоге в реальной жизни Структура слабо применима.

    Соответствие надежнее 🙂 + пошустрее будет 🙂

    Reply
  14. Ish_2

    (13) Ты не погорячился ?

    Из твоего поста : Ограничения на значения ключа..Соответствие надежнее.. пошустрее будет ..

    Получается что применение структуры избыточно.

    Функционал Соответствия полностью покрывает функционал Структуры ,»как бык овцу».

    Структура не нужна ? Так ?

    Reply
  15. artbear

    (14) ИМХО конечно, избыточна 🙂

    Возможно, что во внутренностях структуры есть некая оптимизация для использования строк-ключей, но я что-то по тестам ее не замечал 🙁

    Reply
  16. ildarovich

    (12) Вот ссылка на статью Осипова Тест быстродействия коллекций

    Reply
  17. Арчибальд

    (16) Значит, то 😳

    Reply
  18. Yashazz

    А, снова гений1С… В своё время я замерял на самописной конфе 8.1, так вот структура побыстрее работает, чем соответствие. Точных цифр уже нема, но результат помню. Операций считывания и записи было поровну.

    Reply
  19. Русский

    (11) ну я же говорил, в некоторых случаях соответствие лучше структуры.

    (13)

    artbear пишет:

    в итоге в реальной жизни Структура слабо применима

    И тем не менее, на структуре в 1С:Предприятии построено куча прикладных механизмов, тот же интерфейс завязан на структурах 😉 А соответствие только для специфических целей…

    И я же говорю, соответствие — индексированная коллекция, она быстрее других при извлечении данных, но медленнее той же структуры при сохранении данных в нее.

    (18) в структуре меньшие накладные расходы на запись данных, в соответствии на чтение, вот и получилось, что они «на равных». Увеличьте количество поисков по коллекции (скажем, в 100000 элементов попытаться найти нужные элементы 3000000 раз) и Вы увидите, как структура отстает.

    Reply
  20. ildarovich

    (11)(19) В примерах, приведенных в статье, использовать структуру просто не получится.

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

    В хелпе написано, что структура используется для хранения относительно небольшого количества объектов.

    Другими словами, если структура — hash-map, то его capacity — ограничено. Проведя эксперименты, получим, что структура может хранить максимум 999 свойств!

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

    Но даже если ограничить число объектов 999, то структура как Вариант 5 отстает. Цифры такие: структура — 8,98 мкс, соответствие — 7,52.

    Если есть желание приводить ключи к хорошему типу, используйте тип число и массив! Будет быстрее! Так сделано в тексте статьи [http://infostart.ru/public/78371/]

    в варианте «массив».

    Reply
  21. Ish_2

    (20) Ок !

    Reply
  22. Русский

    (20) ну Вы уж прямо опустили структуру…

    Вот только что открыл конфу Управление торговлей 11.0.4.6. И покурил глобальный поиск, вот что он мне показал:

    Искать: Новый Структура — 2979

    Искать: Новый Соответствие — 215

    Не трудно разглядеть, что разработчики типовой УТ используют структуру более чем в 20 раз чаще, нежели соответствие… Это без учета того, что «внутри» формы, параметры формы представляют собой структуру, и не создаются конструктором Новый.

    P. S. соответствие не панацея, а всего лишь универсальная коллекция, и не стоит ее сувать куда ни попадя. А данная статья и добрая часть комментариев к ней так и призывают это делать…

    Reply
  23. ildarovich

    (22) Вы первый упомянули здесь (9) про структуру. Я вообще в статье эту коллекцию не рассматривал, считая, что у соответствия и структуры — совершенно разное назначение.

    Структура — это модель объекта в оперативной памяти, ее задача придать разнородным данным об объекте необходимую общность, чтобы обращаться с ними как с единым целым.

    999 свойств хватит для описания любого мыслимого объекта. На проигрыш долей микросекунд

    при более ясном и выразительном коде никто не смотрит.

    А соответствие я использовал для ссылок на однородные данные (числа, слова, номенклатура). Ясно, что их может быть гораздо больше 999. Так что никто здесь не умаляет важности и нужности структуры. И приводимая Вами статистика — тому подтверждение.

    Reply
  24. bulpi

    (22)

    То, что разработчики типовой используют структуру чаще, чем соответствие, никак не доказывает, что структура лучше 🙂 Скорее, это компрометирует структуру :))

    Reply
  25. Русский

    (24) 😮

    Позвольте узнать, каким образом это компроментирует структуру? 🙂

    Reply
  26. artbear

    (24) +1

    Reply
  27. Rustig

    …может быть спросить, что «лучше» среди коллекций, у разработчиков 1С, и добавить их ответ в эту статью?

    …для нас, внедренцев, платформа — черный ящик. благо, что есть справка по платформе и этот форум. 🙂

    Reply
  28. KliMich

    (24) +1

    Reply
  29. Dnki

    Спасибо за статью, она избавила меня от экспериментов предполагаемого. Но!

    У Соответствия выявилась слабая сторона:

    1) В качестве ключа иногда нужен поиск по комбинации нескольких полей. Например: Товар+Склад+Партия.

    2) Мне также понадобилось в качестве Значения хранить пару (а может и больше) чисел.

    Пытался запихнуть в него Структуру, но отрабатывает молча, а результата не дает, т.к. Соответствие запоминало не копию данных структуры, а ее адрес. В случае с ТЗ для решения задачи я бы создал несколько колонок.

    Вывод: Соответствие для простых схем. Или для использования в комбинации с ТЗ.

    Reply
  30. Necytij

    (29) Dnki,

    Соответствие не для простых схем. А там где нужно много искать по одноименному ключу.

    Две структуры даже с одинаковыми наборами кортежей ключ-значение, различны, как, например, два документа с одинаково заполненными реквизитами. Поэтому соответствие тут ни при чем. )) Тут уже ваша голова подвела.

    Если искать нужно по нескольким параметрам, то, пожалуй, лучше индексированная ТЗ. А соответствие полезно там где, нужно часто и быстро находить соответствие одному значению, а если не нужно много раз этого делать и набор данных не ОЧЕНЬ большой, то все равно что пользовать.

    Где то встречал совет если не хотите ТЗ, можно сделать соответствием с ключом «значениевстроку(Новый структура(«ключ1,..»,параметр1,2,..))». Но метод как сейчас показали мне тесты довольно плох. Проигрывает индексированной ТЗ в 1.5-2 раза, хоть обыгрывает не индексированную во столько же.

    Заинтересовался немного. Написал обработочку. Берем 1000 поз. номенклатуры, и ищем по совпадении позиций (ссылка, наименование, код). В итоге при поиске 160 000 раз по соответствию получаем около 12.3 сек, из них 10.7 это как раз формирование значениевстроку. Т.е. на сам поиск ушло около 1.5 сек. Для не индексированной ТЗ 18.9 сек. Для индексированной по этим трем столбцам — 5.8 сек.

    Для чистоты тут же и обработка.

    Reply
  31. Dnki

    (30) Necytij, Вы меня просто окрылили! Сами может не подозревая. Значит я на верном пути.

    Посмотрел Ваш пример. И мне не понравилось время на преобразование объекта в строку. Поэтому и я протестировал различные варианты и именно этого фрагмента. В файле я привел полный текст (сам отчет не пойдет, у нас разные базы). А коротко, я сравнил именно такие команды:

    1) Идентификаторы:

    Функция КлючПоискаИдент(П_Товар, П_Склад = Неопределено, П_Партия = Неопределено)

    Возврат Строка(П_Товар.УникальныйИдентификатор())+ Строка(П_Склад.УникальныйИдентификатор())+ Строка(П_Партия.УникальныйИдентификатор());

    2) В строку

    Функция КлючПоискаВстроку(П_Товар, П_Склад = Неопределено, П_Партия = Неопределено)

    Возврат ЗначениеВСтрокуВнутр(Новый Структура(«Товар,Склад,Партия», П_Товар, П_Склад, П_Партия));



    3) В строку, вариация. Сама структура создана вне цикла.

    Функция КлючПоискаВстр2(П_Структура)

    Возврат ЗначениеВСтрокуВнутр(П_Структура);

    Так и есть! ЗначениеВСтрокуВнутр медленнее раза в 2-3 чем сложение идентификаторов. Да и, наверное, строка более длинная.

    А вот предположение потерь от создания объекта Структура подтвердилось частично. Время ускорилось лишь на 1/3.

    Вывод: Разумеется использование индексированной таблицы более толково, системно. Но комбинированная строка — вполне приемлемо. Особенно, если число обращений невелико.

    Reply
  32. Necytij

    (31) Dnki,

    Не подумал сразу что следует для ускорения вынести инициализацию структуры из цикла. НО все же ваш 3й вариант, не совсем верен, вы в цикле должны были переопределять заново параметры для текущего поиска, вы ведь не одну и ту же позицию искать будете. Так что выигрыш от вынесения из цикла инициализации будет еще меньше чем 1/3. А так удачи вам в созидании отчета. Если будет еще полезная информация по этой теме — поделитесь, пожалуйста…

    Reply
  33. Жолтокнижниг

    Каждый тип данных заточен под определенные задачи, и спорить что лучше, что хуже не имеет смысла. Основные преимущества соответствия перед другими(на мой взгляд) почти любой тип ключа и скорость поиска. И исходя из этого надо думать где и как применять.

    Reply
  34. DrAku1a

    Про коллекции и про их быстродействие уже немало сказано:

    http://infostart.ru/public/142517/

    http://infostart.ru/public/116404/

    http://infostart.ru/public/105104/

    В двух словах:

    Самый быстрый поиск => Соответствие

    Моделирование данных* => Структура

    Представление пользователю => СписокЗначений, ТаблицаЗначений, ДеревоЗначений

    Прочие нужды => Массив.

    *-Организованное хранение и удобное обращение в коде к данным как к реквизитам, возможность использовать ЗаполнитьЗначения()

    Удобно!

    Reply
  35. chemezov

    +1000

    Reply
  36. mec

    Отличная статья.

    Уже много лет кодирую на 1С, но вот соответствиями как-то пренебрегал. Теперь буду стараться чаще его использовать в своих работах. Сергей, спасибо за преподнесенный материал

    Reply
  37. Foma4382

    Познавательная статья. Спасибо!

    Reply
  38. LordKim

    (23)

    Максимальное количество элементов Соответствия 99999 (в платформе 8.3.6)

    Это ограничивает использование (например, если с помощью соответствия организовывать поиск по ТЗ в которой больше 100к строк)

    Reply
  39. LordKim

    (38)

    Дополнительная проверка (по замечаниям сообщества) выявила что это не так (при тестировании опирался на набор уникальных ключей, количество которых в ТЗ было 99999, хотя строк в ТЗ было больше)

    Reply
  40. alexsey777

    (22)Ну это объяснимо. УТ 11 построена на управляемых формах. Стало быть нужно передавать данные с клиента на сервер. Собственно для этого идеально подходит структура. Если исходить из вашего комментария выше. Количество элементов небольшое. И читать их на клиенте как правило не нужно. Да и после передачи структуры на сервер как правило извлекать по многу раз данные не нужно.

    Можно конечно это решить и через соответствие. Но, как по мне это уже будет избыточно. Использовать соответствие имеет смысл, если ключом должна быть не строка. Но такие случаи весьма редко встречаются. Отсюда и такая разница в использовании. ИМХО

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *