Кэширование в 1С или уменьшаем нагрузку на сервер




Принцип обмена данными из 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='\

24 Comments

  1. quick

    Поскажите как нормально код оформить?

    Reply
  2. JohnyDeath

    Не поверю, что кэшированием констант и путей к внешним. печ. формам ты добился двукратного снижения нагрузки на сервер.

    Reply
  3. Berrimor

    Мысль логичная, но….. нужно оптимизировать кэшированием на каждом этапе (связано с ГЛОБАЛЬНЫМ перелопачиванием кода) так что мысль здравая, но ни чего нового не несущая, если это несущая модификацию кода модификация, а с теоретической точки зрения ВЫ ПРАВЫ ОДНОЗНАЧНО!

    Reply
  4. Asdam
    Поскажите как нормально код оформить?

    http://infostart.ru/public/19856/

    Reply
  5. JohnyDeath
  6. quick
    Не поверю, что кэшированием констант и путей к внешним. печ. формам ты добился двукратного снижения нагрузки на сервер.

    Сам до сих пор сомневаюсь :D, но эффект точно есть. У меня еще был закэширован один справочник опрашиваемый по нескольку раз при открытии форм и отвечающий за права доступа. В пример не вынес т.к. код идентичный. Он был самый «тяжелый».

    Reply
  7. echo77
    Загрузка на основном сервере ниже 80%

    — эта цифра по какому показателю? Из каких показателей складывается?

    Reply
  8. Valet

    Только нагрузка наверняка никуда не делась, а переползла с сервера на клиента (плюс на клиенте и память занимаемая 1С подрастет).

    И про использование справочников интересно. От запросов совсем отказаться?

    Reply
  9. quick

    Зачем полностью отказываться от запросов 🙂 Всему свое место, просто есть данные, которые меняются редко или почти не меняются, а используются очень часто. Таблица констант кстати очень большая, т.к. в ней еще все периодические реквизиты хранятся. С другой стороны, все равно эти справочники будут постоянно занимать память (если они часто используются), почему бы их тогда просто в памяти не держать? 🙂

    Reply
  10. Elisy

    Кэш на стороне клиента однозначно значительно помогает. Проблему вижу в том, что некоторые величины могут меняться, например, дата запрета редактирования. Кроме того кэширование, например, таблиц на стороне клиента приводит к затратам памяти. В 1С сложно организовать управление кешем. Как альтернативный вариант могу предложить класс Cache .Net из пространства имен System.Web.Caching. Он позволяет положить в кэш значение навсегда, на определенное время, на определенное время после последнего обращения. Таким образом частично снимает описанные мной проблемы.

    Reply
  11. nikakoy

    ТиС. Кешируются в таблицу курсы валют. Поскольку ГлПересчет(…) используется везде (и не по разу на одной форме!!!) при некоторых операциях скорость реально увеличивается на порядки…

    Reply
  12. Rebel2007

    на этой странице вирус Trojan.tempi

    Reply
  13. Ветер в поле

    Давно уже использую кэширование внешних печатных форм — давно заметил, что львиную долю времени открытия формы документа уходит на считывание файлов описаний внешних печ. форм. А когда в день открывается несколько тысяч документов, то это неплохо нагружает процессор. Но мой вариант оптимизации немного другой — при первом доступе к внешним формам я сразу заполняю глКэшПечатныхФорм по всем документам — все равно ведь приходится открывать все файлы.

    Reply
  14. wolfsoft

    За мысль — плюсую.

    Reply
  15. sumv1

    Идея отличная.

    Её должны были в 1С на уровне платформы реализовать.

    Тем более в 8-ке появились параметры сеанса — что-то подобное.

    В приведенном примере с константами есть ошибка:

    глКэшКонстант.Установить(Значение); — так мы потом не получим значение константы

    а надо:

    глКэшКонстант.Установить(Имя,Значение);

    и периодическую константу не получишь методом: ПолучитьАтрибут()

    её можно запомнить при входе

    Может автор нас проверяет? 😉

    Reply
  16. ROM_1C

    Если нечиго делать — можна еще играться с кнопками, списками, и другим хламом, которое так или иначе повлеяет ли на производительность. 😉

    А так идея хороша, но от того что кода станеть больше — никому не будет лучше 🙂

    Reply
  17. Alav

    А если внешние печатные формы сделать на справочнике?. Т.е. реквизит видДокумента (отбор), Наименование, кнПечать, Путь? И этот справочник еще и за кэшировать с помощью Индексированной таблице (в виде дерева), где на первом уровне вид документа, а в тзПотомки соответственно список печатных форм?

    Reply
  18. quick
    А если внешние печатные формы сделать на справочнике?. Т.е. реквизит видДокумента (отбор), Наименование, кнПечать, Путь? И этот справочник еще и за кэшировать с помощью Индексированной таблице (в виде дерева), где на первом уровне вид документа, а в тзПотомки соответственно список печатных форм?

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

    Reply
  19. Alav

    А какая разница куда писать в efd или в справочник? ИМХО обработку не сложно поправить

    Reply
  20. quick

    Привет Жека :)) Еще живет, но свое отживает. По мелочи то там, то здесь подкручиваю… Занялся как видишь выносом «полезняшек» на всеобщее обозрение, что бы добро не пропало.

    Reply
  21. dwarkin

    Вопрос автору: а нагрузка снизится, если БД под SQLем крутится? Версия 1С Предприятия 7.7 SQL

    Reply
  22. quick
    Вопрос автору: а нагрузка снизится, если БД под SQLем крутится? Версия 1С Предприятия 7.7 SQL

    Снизится за счет уменьшения кол-ва запросов. Но надо смотреть что оптимизировать. Мне помогло, кому может не помочь.

    Reply
  23. dwarkin

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

    Будем попробовать….

    Reply
  24. Merlin12042009

    Замечательная статья

    Reply

Leave a Comment

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