<?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='\
«Если на список накладывается несколько отборов, очень важен их порядок (на текущей версии платформы 1С). Правильный порядок отборов:»
а проверяли план запроса в зависимости от порядка условий? Ведь при построении плана запроса сервер SQL сам может поменять порядок отборов, если посчитает нужным (в зависимости от тех же индексов и др. условий).
(1) MoGar,
Проверял, сейчас повторно запустил проверку с 2 отборами двумя вариантами:
1) Отбор по пустому менеджеру; отбор по вычисляемому полю — 458мс
2) Отбор по вычисляемому полю; отбор по пустому менеджеру — 2278мс
В тексте выполненных sql запросов различия в порядке условий сохранились, планы запросов разные.
К сожалению, во втором случае ms sql не поменял порядок условий, а также выбрал неоптимальный план запроса. Повлиять на это со стороны 1С пока не представляется возможным, кроме как накладывать отборы в «правильном» порядке.
Проверено также на типовой БП3.0, в запрос полного списка проводок добавлено «тяжелое» вычисляемое поле:
(ВЫРАЗИТЬ(ХозрасчетныйДвиженияССубконто.Регистратор.Номер КАК СТРОКА(10))) + «_ЛЯЛЯ» КАК ЛЯЛЯ
На список накладывал 2 вида отборов:
1) СчетДт = 60.01; ЛЯЛЯ содержит «ЛЯ»,
2) ЛЯЛЯ содержит «ЛЯ»; СчетДт = 60.01,
По сумме времени запросов ( по данным profiler’а), первый вариант отработал в 3,6 раза быстрее, чем второй.
Если есть возможность, проверьте у себя, было бы интересно увидеть результаты на другой машине.
По поводу флага «Динамическое считывание данных». Очень для меня интересный момент.
Исходя из ваших рекомендаций, я понял что почти всегда имеет смысл его отключать, кроме случая тяжелых запросов и малой вероятности необходимости скролла. Т.е. можно все бросать и бежать снимать галку во всех формах простых журналов документов? Ведь скролл будет комфортнее работать и реже подтормаживать. Почему тогда по дефолту галка всегда стоит? Может, не все так гладко? Я понимаю, что минусом будет увеличение вероятности отображения неактуальной информации. Других минусов нет?
Поставил эксперимент, получил странный результат.
При снятии галки динамического считывания, подтормаживания при скроллах остались в рамках тех же порций, что и были. Т.е. чуть больше размера экрана.
Но при этом на динамическом списке с произвольным запросом с соединением среза последних по регистру сведений подтормаживание резко увеличилось. Т.е. похоже на то, что из БД выбирается в самом деле увеличенная порция данных, но выбирается она с той же самой периодичностью! Т.е. никакого профита — одни убытки. Возможно, дело в используемой СУБД.
Основные таблицы везде прописаны.
сервер 8.3.6.2390 на x64 Ubuntu 14.04, сервер PostgreSQL 9.2.4 на другом x64 Ubuntu 14.04
В общем, осторожней с этой галкой.
имхо, нужно тоже соблюдать баланс индексов. когда их много, то таблицам это не очень нравится… как обычно, используем здравый смысл ))
(6) Еще раз.
При снятии галки на «тяжелом» динамическом списке наблюдалось резко увеличившееся подвисание при прокрутке. Не при длительной прокрутке, а при обычной. Если бы дело было только в обращении на сервер приложений за порцией уже считанных данных, такого бы не наблюдалось. Время «подвисания» должно было либо остаться таким же, либо уменьшиться. Так что либо при обычной прокрутке каждый раз фигачится запрос на 1000 элементов, либо пропала какая-то другая оптимизация.
(7) herfis,
Странно, что подвисания увеличиваются, у меня обратная ситуация.
Здесь подтверждается, что при запросе 1000 строк, данные запоминаются в буфере на сервере, а потом, передаются на клиент частями. Видимо у Вас этот буфер работает медленнее, чем повторный запрос к БД.
На своей базе проверил — при отключенном динамическом считывании, при небольшой прокрутке запрос к БД не происходит. И прокрутка быстрее, чем при динамическом считывании.
(8) Я верю, что у вас так. Это, по крайней мере, логично.
Но в моей конфигурации, которую я описал выше, все не так радужно.
Вполне может быть что это косяк в линуксовой версии сервера приложений.
А я вот не совсем понял, что значит эта фраза «При соединении таблиц использовать индексы»? Использовать временные таблицы в запросе динамического списка нельзя. Про какие индексы вы говорите? Поясните пожалуйста.
(10) Речь о так называемом «попадании в индекс». Т.е. стараться в запросах эффективно использовать существующие индексы физических таблиц, а при острой необходимости — создавать недостающие. Самое банальное для примера — если в запросе динамического списка используется соединение с очень большим справочником по доп-полю с высокой селективностью, то имеет смысл это доп-поле проиндексировать.
(11) Как? Можно пример?
(12) Индексы физических таблиц. Например, в динамическим списке связывается физическая таблица справочника «Товары» и РС «Состояние контрагентов» по полю «Контрагент». Так вот желательно, чтобы и в справочнике — реквизит «Контрагент» был проиндексирован (это свойство реквизита), и в регистре — измерение «Контрагент» было проиндексировано (свойство измерения, имеет смысл если оно не первое измерение).
А, менять индексирование в реквизите. Это не подходит. Без изменения конфы надо.
(14) У вас какой-то типовой динамический список подтормаживает?
Без изменения конфигурации проиндексировать не получится (средствами sql можно, но нежелательно).
Проблема немного другая. Есть УТ 11.3. В ней есть форма списка справочника номенклатура. Вот запрос ,что там используется.
Показать
ПРоблема в том, что иногда открываешь форму и она открывается через 2-3 секунды, а иногда через 10 минут. Вот и не понимаю почему. Может подсжадите?
В первую очередь, проверьте «вытащенные через точку» поля в пользовательском режиме. Их отключение может увеличить производительность.
База на SQL? Попробуйте пересчитать статистику и перестроить индексы, часто именно это является причиной нестабильной работы.
Если ничего не помогло — нужен детальный анализ через профайлер.
Ну и как вариант, чтобы убедиться, что причиной долгого открытия формы является именно динамический список, попробуйте отключить его.
Поля через точку примитивного типа. База файловая. Без динамического списка все летает.
а как понять какие поля проиндексированы? В регистре накопления например, есть ресурсы есть измерения, что из них должно индексироваться?
Статья помогла найти в чем причина зависания при открытии формы списка регистра сведений с динамическим списком. Спасибо!