Нарастающие итоги в запросе и методы ускорения его выполнения.




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

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

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

<?php // Полная загрузка сервисных книжек, создан 2024-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='\

99 Comments

  1. PowerBoy

    А код где? Непонятно так.

    Reply
  2. anig99

    (1) готовый код конечно могу выложить, если непонятно. По мне, так лучше алгоритм раскрыть, чем тупо выложить код, в котором нужно разбираться. В течении дня код дополню.

    Reply
  3. anig99

    Буратино был тупой…тупой как дрова (:

    Зыбыл как статью пометить. Исправился

    Reply
  4. Трактор

    Нужен пример запроса. Однозначно. Запрос, чувствуется, будет довольно сложным.

    «Видала я котов без улыбок, но вот улыбку без кота ещё ни разу» (с) Алиса

    Теперь по-русски.

    Я видал много программ без описаний, но вот описание без программы встретишь не часть.

    Reply
  5. anig99

    (4) ща прямую ссылку кину.

    Reply
  6. anig99

    Сама реализация на http://infostart.ru/public/20221/ — ссылка на файл «Новый запрос»

    Reply
  7. anig99

    (4) и вроде бы это уже с утра статья

    Reply
  8. Трактор

    (7) не важно статья это или программа. Важно что есть описание к коду, а кода нет. Теперь есть ссылка на код и то хорошо.

    Reply
  9. hogik

    (0)

    Данная задача (по самой сути алгоритма) решается легко и эффективно без запросов. Решать данную задачу запросом — это самоцель? Или в «1С 8.х» другого способа решения данной задачи не существует?

    Reply
  10. anig99

    (9) я не пишу статьи для развлечения и самоцелей. В 1с есть замечательные механизмы по быстрому формированию отчетов: всевозможные консоли отчетов, создание отчета как внешней обработки и создание внешнего отчета. И если есть возможность решить задачу только средствами запроса, то сделать отчет можно без лишних усилий и лишнего кода. Кроме того, есть ещё два плюса, в которых я не уверен, так ли это — запрос выполняется на сервере, а значит на предположительно более мощной машине — отчет по дебиторке с запросом на небольших объемах данных выполняется быстрее отчета на встроенном языке. А на больших объемах данных быстрее оптимизированный вариант. Второй фактор — работа с web-клиентами (тут я только предполагать могу, т.к. слышал что-то краем уха, поэтому не буду утверждать)

    Reply
  11. hogik

    (10)

    Видимо в (9) я плохо изложил свою мысль. Попробую сказать иначе — данную задачу надо решать без применения запроса…

    Reply
  12. Шёпот теней

    всегда ЕСТЬ мода… нынче ВСЕ увлеклись Запросами … ХМЛ-ями …

    .. просто сказали — так надо … просто кто-там и ему тАк удобно — вот теперь все на него и равняются …

    … (11) … так КАК же данную задачу надо решать …? товарищь hogik..?

    … вотРасскажите …

    Reply
  13. anig99

    (11) видимо плохо объяснил свою… Данную задачу МОЖНО решить без применения запроса и это наиболее привычный для многих способ. Но наиболее привычный — это не во всех случаях наиболее простой или наиболее оптимальный. Ещё раз — применение алгоритмов из статьи существенно ускорило выполнения отчета на больших объемах данных.

    Вопрос регулярно подымается на различных форумах. Иногда очень неудобно увеличивать срок разработки отчета из-за необходимости писать код для программной обработки данных и их вывода.

    Кроме того, методы последовательного приближения вполне применим и для программного исполнения.

    Reply
  14. anig99

    (12) он предлагает пройтись по таблице значений и последовательно наращивать итоги…

    и мода-не мода, но индексированность данных не самый последний фактор в скорости расчетов.

    Reply
  15. hogik

    (13)

    «применение алгоритмов из статьи существенно ускорило»

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

    Reply
  16. hogik

    (12)

    » так КАК же данную задачу надо решать …? товарищь hogik..?»

    Уважаемый Александр («Шёпот теней»), я Вам не товарищ. А если это «партийное» обращение, то тем более не к месту. Т.к. будучи рожденным в 1955 году, я даже в комсомоле не состоял… 😉

    А решение описано в предыдущем (15) сообщении данной темы.

    Reply
  17. anig99

    (15) ускорение относительно именно варианта с программным решением. Между прочим, 3 оператора, подойдут только если нам нужен итог… а если брать не одного контрагента, да ещё и не только в одном разрезе… Пример в статье для самого простого случая. Реальные задачи часто много сложнее. Я не утверждаю, что программный способ плох. Я говорю, что есть задачи, где он менее эффективен и удобен, чем запросный метод.

    Reply
  18. Шёпот теней

    … раньше форма и содержание — хранились вместе, потом отдельно … теперь даже результаты отделены от данных …

    … есть язык программирования процедурный а есть декларативный …

    … зачем бегать по документам — когда результаты хранятся не там где хранятся данные … есть сервер (как хранилище) и есть пльзователь (как клиент) … запрос — работает тАмА а процедура Тута …

    … есть «правильно» с т.з. производительности и общей политики а есть «правильно» с т.з. простоты и быстроты …

    … гармония в середине …

    … никогДА не думал что товарищЬ это оскорбление — господин hogik …

    … вОт …

    Reply
  19. hogik

    (17)

    «3 оператора, подойдут только если нам нужен итог»

    «Пример в статье для самого простого случая.»

    Ну и мой пример для этого самого случая. 😉

    «говорю, что есть задачи, где он менее эффективен и удобен, чем запросный метод.»

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

    Спасибо за интересную беседу. Желаю успехов.

    Reply
  20. anig99

    (19) да, видимо, немного нужно изменить статью — оговорку в начале более подробную сделать. Статья я ведь не о конкретной задаче (пример, это всё же пример — максимально упрощен, чтобы алгоритм понятнее был)

    Reply
  21. anig99

    (18) дзен-программирование, программирование по фен-шую, дао процедуры и функции…(: Не удержался (:

    Но идея верная.

    Reply
  22. Шёпот теней

    (21) … ))) …

    … цель не определяет средство — но средство определяет решение …

    найдя связь между целью и решением исключим мучения относительно выбора средства …

    … )))

    … вОООттАААкойФенШуй …

    Reply
  23. artbear

    (0) Тогда еще добавить, что при больших выборках применение данных методов вполне способно очень сильно загрузить сервер 🙁

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

    Сам использую их таким образом.

    Reply
  24. anig99

    (23) несколько раз в статье написано о времени выполнения запроса (нагрузке на сервер), а так большая часть статьи написана об ОПТИМИЗАЦИИ, чтобы время выполнения и нагрузка на сервер были минимальны.

    Reply
  25. ZLENKO

    В 7-ке не было вариантов — описанную задачу можно было решить только кодом. В 8-ке можно и кодом и запросом. Запросом получаем и более гибкое по возможностям решение и более быстрое.

    Кстати в моем отчете http://www.infostart.ru/public/21968/ используется вариант автоматического ограничения периода без потери «точности» (можно принудительно ограничить период с потерей части детализации если производительность не достаточна).

    Reply
  26. anig99

    (25) ну собственно это один из тех отчетов на которые я намёкивал (: Просто на моей базе без оптимизации одним запросом вообще труба, а вариант с искусственным ограничением числом дней не подходит по идеологическим соображениям

    Reply
  27. Ish_2

    Как же я пропустил ! Очень нужная статья.

    Я извиняюсь , но всё читал мельком, кроме текста запроса.

    Да простит меня автор , но всё же лучше придерживаться рекомендаций 1с , и оформлять пакетные запросы , используя временные таблицы.

    На эту тему на ИС ,кажется , сказано уже немало.

    Смутило также , упоминание в комментариях «загрузки сервера» без уточнения :»приложений» или «БД».

    Думаю, метод оптимизации зависит от реализации «трехзвенки» .

    Возможна ситуация , когда выгоднее загрузить выделенный сервер БД запросом , чем писать оптимизационный код , используемый в сервере приложений.

    Reply
  28. anig99

    (27) конкретно код в статье не мой, лень было писать простой код (: В обработке по дебиторке (ссылка в статье), где всё это реализовано — пакетные запросы и временные таблицы.

    А про комментарии…Я не подкован теоретически. Поэтому готов почитать хороший материал с примерами про производительность выполнения кода в различных вариантах.

    Запрос, выполнение кода на машине, выполнение на сервере, один запрос, множество подзапросов в цикле, множество подзапросов в цикле на сервере….

    Reply
  29. Ish_2

    А кто здесь подкован теоретически ?

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

    Это обстоятельство может быть существенным при выборе варианта оптимизации.

    Материалы с примерами производительнсти для разных вариантов реализации «трехзвенки»(клиент-сервер приложений-сервер баз данных) тоже бы почитал с удовольствием.

    Reply
  30. Ish_2

    Саш, я по-простому ?

    На мой взгляд, лучшим вариантом оптимизации будет следующий :

    Получим из виртуальной таблицы Обороты регистра ПродажиПоДисконтнымКартам правильно отсортированную таблицу значений Тоб

    со структурой Карта, Период , СуммаОборот.

    Добавим в Тоб типизированную колонку СуммаНакопления.

    Теперь пишем :

    ТекКарта = НеОпределено;
    Для каждого Строка из Тоб Цикл
    Если Строка.Карта <> ТекКарта Тогда
    СуммаНакопления = Строка.СуммаОборот;
    ТекКарта = Строка.Карта;
    Иначе
    СуммаНакопления = СуммаНакопления + Строка.СуммаОборот;
    КонецЕсли;
    Строка.СуммаНакопления = СуммаНакопления;
    КонецЦикла;

    Показать

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

    Итак , если сравнивать время исполнения запроса в тексте темы и алгоритм :

    1. Выгрузка из запроса и Получение Тоб

    2. Приведенный код

    3. Загрузка в запрос таблицы Тоб и получение временной таблицы

    То выигрыш при 100 000 записей в Тоб должен составить не менее 3 раз.

    Если количество записей 1 000 000 и более то выигрыш должен составить не менее 5 раз.

    Reply
  31. anig99

    (31) здесь я абсолютно согласен. С диким замедлением я тут же столкнулся, когда попытался получить нарастающие итоги в запросе. Покумекав и погуглив, я выяснил причину, но единственным решением нашел ограничением срока для уменьшения выборки.

    Т.к. в тот момент я осваивал пакетные запросы и решил всё-таки ещё подумать, как можно обойти это ограничение, чтобы можно было обойтись средствами быстрого создания отчетов 1с 8. Результатом стал алгоритм последовательного приближения.

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

    Если сравнивать запрос с последовательным приближением и выполнения кода без хитрых оптимизаций, то запрос выигрывает.

    Это не теория. Я сравнивал по производительности отчеты по дебиторке и свои (разные варианты), и чужие. Пока быстрее всего — оптимизированный запрос.

    Вопрос остается в другом — стоит ли отчет такой мудренной оптимизации. Для дебиторки — стоит. С получаса я сократил время до 10-20 сек и теперь могу сравнивать в одном отчете разные периоды достаточно быстро. Со старым отчетом мне даже в голову бы не пришло получить график просроченной дебиторки в разрезе дней за 3 месяца. А тут — ноу проблем.

    Reply
  32. Ish_2

    (31) Саша , я тебе могу задать с десяток вопросов. Но лучше о другом.

    В чем -то я согласен с Чебуром.

    Статья должна быть такой . Выкинуть словесную дребедень .

    Оставить : Подробный пример описания метода нарастающих итогов.

    В примере выкинуть регистры — оставить только абстрактные таблицы.

    Постановка задачи. (абстрактная, выкинь ты эти ПродажиПоДиск…)

    Дано : таблица Т1 , структура Поле1 , Поле2 и т.д.

    таблица Т2 , структура Поле1….

    Нужно получить Таблицу 3 со структурой ….

    В теме автора допускается вставка «таблиц». Заполнил для наглядности

    Т1 и Т2 простенькими значениями и пошел текст запроса с показом изменений в демо-таблицах Т1 и Т2.

    Вот так будет по-взрослому.

    Reply
  33. anig99

    (32) а можно поподробнее про авторов и таблицы (можно в личку), а то не всё понял, немного сумбурно.

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

    Reply
  34. Ish_2

    Зачем в личку ? Тут ничего неприличного нет.

    Теперь я тебя не понял. Постараюсь по-другому.

    Тема должна должна быть понятна читателям. См.(1)

    Как её сделать наглядной и понятной ?

    Ты сможешь описать её на уровне таблиц ?

    Дана : Т1 со структурой … Т2 со структурой..

    Получить Т3 со структурой ..

    Reply
  35. Ish_2

    Я, конечно, ничего не понял про метод нарастающих итогов , но начал подозревать ,что мы говорим про разные задачи.

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

    таблицу Тоб — не получить. Заметь Тоб получена не для одной карты как у тебя в запросе , а для всех карт сразу.

    Ты мне говоришь про что ?

    что есть еще какой-то метод получения Тоб ?

    или ты имеешь ввиду какую-то другую задачу ?

    Reply
  36. anig99

    (35) хмммм…. Я говорю о том, что как раз есть методы быстрее чем привычные, как для кода, так и для запросов. Если стоит просто задача получить итоги с нарастанием без дополнительных ограничений, то просто в цикле пройтись по таблице — несложно. Если есть условие сделать это в запросе (например для того, чтобы написать отчет только с помощью конструкторов без кодинга), то….ну там в статье написано. Если отчет простой, то зная как только запросом получить нарастающие итоги можно существенно облегчить себе жизнь при его создании.

    НО…. можно наложить ещё одно условие — большой объём данных. Оба варианта при этом дают неудовлетоворительные результаты по скорости. Причём запрос начинает существенно проигрывать по скорости… Для оптимизации и кода, и запроса можно применить метод последовательного приближения.

    Reply
  37. Ish_2

    (36) Да .. опять загадочно.

    Ты утверждаешь :

    1. что временную таблицу Тоб из (30) (внимание ! именно её, содержащую информацию для всех карт по периодам) ты получишь быстрее ? для большого объема информации ?

    Так ?

    2. Или ты утверждаешь, что целиком эту таблицу не получаешь и в твоем алгоритме она в таком виде не используется ?

    Я по-прежнему тупо исхожу из текста приведенного тобой запроса

    и последующих утверждений , что в получении результата этого запроса — всё дело ! Я лишь убрал условие, ограничивающее выбороку одной картой,

    а сделал выходную таблицу для всех карт.

    Если так , то по-моему скромному мнению , быстрее этого простого способа что-то придумать тяжело.

    Reply
  38. Ish_2

    Впрочем , получение Тоб — это только часть алгоритма.

    Можно прикинуть следующий вариант : запрос, выбирающий нужные движения из вирт.таблицы Обороты.

    И лишь затем код , получающий Тоб

    Выбрать ДисконтнаяКарта, СуммаОстаток Поместить Остатки ИЗ Регистр.ПродажиПоДисконтнымКартам.Остатки(&Дата)
    //
    Выбрать Об.ДисконтнаяКарта,Об.Период, Остатки.Сумма из
    РегистрНакопления.ПродажиПоДисконтнымКартам.Обороты(, , Регистратор)
    как Об  ВнутреннееСоединение Остатки по Об.ДисконтнаКарта=Остатки.ДисконтнаяКарта
    Итоги по Об.ДисконтнаяКарта

    И далее понятный код получения Тоб из дерева выборки.

    ВыборкаКарт = Запрос.Выполнить.Выбрать()
    Пока ВыборкаКарт.Следующий() Цикл
    ВыборкаДокументов = ВыборкаКарт.Выбрать();
    Пока ВыборкаДокументов.Следующий() Цикл
    ….// создаем строку Тоб
    Если //Условие// Тогда
    Прервать;
    КонецЕсли;
    КОнецЦикла;
    КОнецЦикла ;

    Показать

    Итак, Саша, мы сделали очень легкий запрос к остаткам вначале, затем

    сделали всего один запрос с внутренним соединением. Да база ,очень большая, но и запрос простой без суммирования вовсе — раз , условие внутреннего соединения простое — два. Особо обращаю внимание мы обратились к базе с простыми запросами на выборку всего два раза

    И в конце простой обработкой с прерыванием цикла по условию создали всю таблицу Тоб.

    Ей-Богу , что можно придумать быстрее и проще ? Как ?

    Какие нарастающие итоги ? Какие последовательные приближения?

    Зачем это всё ?

    Не томи.

    Reply
  39. anig99

    (37)

    В статье же вроде написано всё.

    Необходимость оптимизации требуется не для запроса с дисконтными картами — это всего лишь простой пример получения нарастающих итогов в запросе. Запрос по производительности сильно зависит от объема данных. Поэтому у нас получается так:

    Код

    +Скорость выполнения — скорость выполнения растёт линейно в зависимости от объема данных

    -Скорость написания программистом отчета — если всё остальное в отчете реализуемо в рамках запроса и писать код не нужно, то для нарастающих итогов придется писать дополнительную процедуру, потом процедуру вывода отчета и т.д.

    Запрос

    +Скорость написания программистом отчета — весь отчет можно сделать автоматом на основе одного запроса

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

    Остается только выбрать какой из вариантов более подходит под конкретную задачу.

    Дальнейшая статья описывает как в более узком ряде задач можно оптимизировать алгоритм.

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

    З.Ы. Ну уж не знаю как объяснить необходимость оптимизации, если вместо 30 минут с помощью кода получаем за 10-20 секунд с помощью оптимизированного запроса.

    Reply
  40. artbear

    (38) Уже говорили, что подобная схема с нарастающими итогами часто бывает нужна именно в запросах для использования универсальных отчетов.

    например, чтобы в СКД сделать некий отчет без доп.кодирования.

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

    Reply
  41. Ish_2

    (39) Приведи описание и текст запроса. Это просто слова.

    Напиши еще одну статью , уже без разбора альтернативных вариантов.

    Только тексты запросов и объяснения к ним. Остальное — лишнее.

    (40)

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

    Это про что ? Про предложенный алгоритм в (38) ?

    Любое множество данных есть не слишком большое.

    Что-то более вразумительное к цитате добавить тяжело.

    Reply
  42. anig99

    (41) Отдельно запрос есть и опубликован. Ссылка в тексте.

    Если я вынесу в отдельную статью описание запроса, то это потребует тех же объяснений…Что зачем и почему, как решить по-другому…чтобы понять проблему нужно полностью её описать. Это как объяснять человеку, который не видел электричества работу атомного реактора без объяснения зачем требуется такое устройство и где его лучше применять и строить и как без него обоитись

    Reply
  43. Ish_2

    (42) Саша, я просто капризный. Много слов меня раздражает. Я ведь неслучайно привел свой текст запроса и обработки. Чтобы без лишних рассуждений было все абсолютно понятно.

    По-прежнему считаю , что так представление метода (алгоритма) не делается. Но о вкусах не спорят.

    Я привел тебе алгоритм . Скажи метод нарастающих итогов какую даст прибавку в быстродействии , по сравнению с моим запросом и обработкой ?

    В конкретно твоей базе ? 5 раз, 10 раз ? сколько ?

    Ты мне дай одну ссылку и имя файла которое надо скачать.

    А то там много чего написано и ссылок внутри.

    Reply
  44. anig99

    (43) кол-во слов сокращу, а содержание всё-таки оставлю (:

    Метод нарастающих итогов — увеличит время выполнения.

    Неоптимизированный код:оптимизированный по-моему запрос 20:1

    Оптимизированный по-твоему код:оптимизированный по-моему запрос минимум 5:1

    http://infostart.ru/public/download.php?file=54832

    Reply
  45. Ish_2

    (44) Замечу , 5:1 — это подозрительно и очень круто. Но если это так , то конечно , сложность алгоритма без всякого сомнения оправдана.

    Но уменя еще вопрос . Саша , а рассматривался такой вариант :

    Выбирается Период «П1» , допустим месяц . И для этого периода запускается алгоритм (38). Получили Тоб.

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

    Для полученной временной таблицы непогашенных карт алгоритм (38) запускается еще раз с периодом «П2» , допустим «год».

    И далее период «П3» — уже весь интервал для оставщихся карт с непогашенным долгом.

    Не это ли есть последовательные приближения ? При таком подходе

    Периоды П1,П2,П3 должны быть такими , чтобы количество записей в Тоб на каждом шаге уменьшалось в десятки , сотни раз

    Речь идет о конкретной базе.О твоей. При таком подходе соотношение времен выполнения моего и твоего алгоритма должно быть

    1:2.

    А при удачном подборе периодов П1,П2,П3 можно жобиться 1:5.

    Это прогноз , разумеется.

    Ну ,как ? согласен ?

    Reply
  46. anig99

    По поводу твоего алгоритма — удачный. Недостаток действительно только в правильном подборе сроков деления. На это нужны эксперименты… Можно его модифицировать приращивая периоды не с увеличением интервальности, а равными долями. Т.е. не месяц, год и т.д. А месяц, предыдущий месяц, позапредыдущий месяц и т.д.

    Только вот опять тут нельзя реализовать данный алгоритм в рамках одного запроса. А так очень неплохой алгоритм.

    Я тут на тебе попробую различные варианты объяснения своего алгоритма. Какой понятнее и проще…

    Мой алгоритм идет наоборот от более крупных периодов к более мелким. Но рассматриваются не документы внутри периода, а итоговые значения по периоду (т.е. сумма). Рассмотрение идет от сегодня в прошлое. Если сумма увеличения долга за год больше, чем долг, то дробим период на месяцы рассматривая опять только итоги, если меньше, то рассматриваем следующий год. Такая же фигня на уровне месяцев и так до уровня регистраторов.

    В результате имеем набор таблиц

    Контрагент Полных лет долга

    Контрагент Полных месяцев долга

    Контрагент Полных дней долга

    Контрагент Документы долга в самый давний день долга

    Из этих таблиц уже можно получить полный список документов долга.

    Reply
  47. Ish_2

    Ок. Черт с тобой. Пробуй на мне свой алгоритм.

    Я немного туповат , но буду стараться.

    Свои замечания по (45) и как они у тебя реализованы оставю чуть позже.

    Reply
  48. Ish_2
    Reply
  49. anig99

    Про двойное обращение замечание верно. Но если я правильно помню, то общая таблица взаиморасчетов потом используется ещё — чтобы выводить весь список документов за период долга. Про индексировать… ну я по наитию его туда вставил.

    КонецПериода вставил как двойной предохранитель.

    Reply
  50. Ish_2

    (49) И всё-таки двойное обращение ненужно . Проще потом обратиться еще раз прямо к самой виртуальной таблице Обороты. По размерам эти огромные таблицы одинаковы.

    Reply
  51. artbear

    (48) Цитата: «А в принципе оптимизатор запроса сам построит временный индекс по этому полю»

    я лично не стал бы рассчитывать на это неявное поведение оптимизатора, у его и других задач/приоритетов полно.

    Если индекс все равно нужен, т.к. будет использоваться в фильтрах или соединениях, нужно задавать его явно!

    Reply
  52. artbear

    (48) Использование «КонецПериода» — также вполне нормальное явление.

    Автор гарантирует, что запрос отработает нормально для любой даты.

    Reply
  53. Ish_2

    В (48) Придирки.

    (51) Согласен, но сам ставлю Индексировать лишь придальнейшем неоднократном использовании .

    (52) Согласен.

    Reply
  54. Ish_2

    К загадочному (40).

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

    Reply
  55. Ish_2

    Саша, на всякий случай.. Мало ли ..

    Мне тут как то приходилось объяснять Шепоту , что такое оппонент и в чем его задача. Задача его «наводить критику». Вот я навожу.

    Смотрел , смотрел текст запросов. Затем еще раз прочитал твои объяснения в статье.

    Критика1. Если ты хочешь , чтобы кто-то что-то понял , то так алгоритмы не представляют и не офомляют. Нужен упрощенный текст запроса в теме и сквозной понятный пример ( с заполненными демнострационными таблицами в тексте)

    Критика 2. Вложенные запросы в тексте призводят жуткое впечатление.

    Давно пора перейти к временным таблицам. Легче рассматривать , проще искать ошибки и т.д. Уж сколько говорилось на эту тему и фирмой 1с и пользователями ИС…

    Критика 3. Теперь по сути.

    Теперь для меня, вне всякого сомнения, твой запрос по скорости проиграет слегка оптимизированной (почти тупой) выгрузке в таблицу значений и заполнения её необходимыми данными за один проход (подчеркиваю , вся выходная таблица будет получена за один проход).

    Алгоритм этот и проще для понимания.

    Но первая прелесть твоего алгоритма именно в том, что реализуя весь алгоритм в одном запросе — мы «отвязываемся от клиента» и передаем всю нагрузку вычислений на сервер баз данных.

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

    Критика 4. Дойдя до получение таблиц УвеличениеДолгаДень, Ув..месяц, Ув..Год, я не сомневался что последует дальше. Ан нет. Мне всерьез непонятно ,зачем так сложно ? Спорить тут бестолку. Алгоритм у тебя работатет.

    Про оптимальный, на мой взгляд, алгоритм лучше самому писать статью.

    Вот брошу пить — я за Вас возьмусь !

    Если напишу — приглашу тебя и назначу самым злобным оппонентом.

    Reply
  56. I_G_O_R

    ксати, в ЗУПе для подсчета доходов физлица по периодам нарастающим итогом используется такой же метод как в статье, так что зачёт

    Reply
  57. Ish_2

    (56) Не-а. Не убедил.

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

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

    Reply
  58. I_G_O_R

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

    Reply
  59. Ish_2

    (58) Я здесь приводил код в (38) кажется втупую весь регистр в выборку

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

    Хотя можно сделать три запроса : Сравнить текущийдолг с оборотом за месяц — все попавшие выгрузить, остальные сравнить с оборотом за год и т.д

    Reply
  60. I_G_O_R

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

    Reply
  61. Ish_2

    (60)Постой, Если ты обращаешься в конструкторе запроса к таблице обороты там должно быть Поле МоментВремени. Сравнивать, упорядочивать надо естественно по нему.

    Reply
  62. Ish_2

    Это вопрос Саше : почему у тебя в тексте запроса нигде не применяется МоментВремени. И что будет если Два или несколько документов имеют одинаковую дату и время ?

    Reply
  63. I_G_O_R

    (61) а вот и нету 😀 , значит надо брать таблицу записей.

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

    Reply
  64. Ish_2

    (63) Так дело не пойдет . Загадками бросаешься.

    Я считаю , что Таблицу ОстаткиИОбороты эффективно использовать в данной задаче не удастся. Ну.. так мало ли , что я считаю . Если думаешь, что из этой таблицы можно что-то выудить — пиши статью.

    И я потянусь за тобой со своей статейкой : нет, товарищи , так делать нельзя. Глядишь , скука и пройдет…

    Только условие Саши — весь алгоритм в одном флаконе (запросе) должно быть выполнено.

    Reply
  65. anig99

    (62) Гы-гы…Думал когда же всплывет (: Для того, чтобы отсортировать документы с одинаковой датой сравниваю ещё по ссылке <=. Ведь что есть Момент времени? Виртуальный тип, который содержит в себе Дату и ссылку.

    (63) Итоги то с нарастающим, но там все итоги, а нам нужны только по документам увеличивающим задолженность

    С разными виртуальными таблицами есть ещё лажа с Границами, в таблице остатки нельзя задать условие не границу, её туда надо в виде параметра запихивать, а в ОстаткахИОборотах есть соответствующий параметр, который преобразовывает дату в границу. Вот тут и есть глобальная подстава для СКД… Штатным конструктором нельзя границу в запрос СКД передать, только с помощью кода. Поэтому когда быстро ваяешь запрос по виртуальной таблице Остатки в СКД, нужно помнить, что граничные значения не получишь.

    Reply
  66. Ish_2

    (65) Будем считать , что (60) Игорь писал НЕ про твою обработку и что-то перепутал.

    Ага , вот нашел у тебя в условии соединения :

        И (ВЫБОР
    КОГДА ПериодыРегистратор.Период < УвеличениеРегистратор.Период
    ТОГДА ИСТИНА
    ИНАЧЕ ВЫБОР
    КОГДА ПериодыРегистратор.Период = УвеличениеРегистратор.Период
    ТОГДА ПериодыРегистратор.Регистратор <= УвеличениеРегистратор.Регистратор
    ИНАЧЕ ЛОЖЬ
    КОНЕЦ
    КОНЕЦ)

    Показать

    Такое выражение в условии соединения есть предложение оптимизатору запроса — отдохни , это не для тебя — мы будем тормозить ! и обращаться не к индексу ,а к каждой записи самой таблицы!

    Чтобы дать хоть какой то шанс бедному оптимизатору , на мой осторожный взгляд, лучше написать :

     И ( ПериодыРегистратор.Период < УвеличениеРегистратор.Период ИЛИ
    ПериодыРегистратор.Период = УвеличениеРегистратор.Период И
    ПериодыРегистратор.Регистратор <= УвеличениеРегистратор.Регистратор)
    Reply
  67. I_G_O_R

    (66) я такой код вообще нигде невидел 😮

    Reply
  68. Ish_2

    (67) Я скачал из ссылки в (44)

    Reply
  69. I_G_O_R

    а в отчете по ссылке из (44) выдает везде одинаковые цифры, где тут итоговая сумма?

    Reply
  70. Ish_2

    (69) У меня нет возможности проверить и я смотрю только текст запроса.

    Reply
  71. I_G_O_R

    (68) да я видел ссылку, скачал а там пусто 😮 , потом оказывается нашел глюк в платформе 8.1.15. Делал так:

    1. Меню-Файл-Открыть

    2. Выбираю тип файла: Внешняя обработка

    3. что-то не вижу 😮 , в поле «Имя файла» набираю первые буквы и вот он, нажимаю открыть, а там пусто 😮

    Если открыть без фильтра или с правильным фильтром(Внешния отчет), то открывается все ОК 😀

    Reply
  72. I_G_O_R

    вот ещё, может он и правильный, может это я что-то не понимаю ❓

    Reply
  73. Ish_2

    (72) Я чего -то поплыл . А входящее плат.поручение и как туда попало ?

    Reply
  74. I_G_O_R

    (73) у нас в России платежное поручение влияет на взаиморасчеты

    Reply
  75. Ish_2

    (74) Виноват.

    Надо съездить в Ростов-на-Дону(Россия) , посмотреть как там люди живут.

    А у тебя какие вопросы по (72) ?

    Reply
  76. I_G_O_R

    (75) я думал, в отчете должна быть сумма нарастающим итогом.

    Reply
  77. I_G_O_R

    (64) вот пример как можно использовать таблицу ОстаткиИОбороты для расчета суммы нарастающим итогом

    Reply
  78. Ish_2

    (77)Это что ? Чего то я опять потерялся.

    Зачем нам таблица Контрагент, Регистратор, Оборот, КонечныйОстаток ? ЧТо Она дает ?

    Нам нужно на текущий долг контрагента набрать документов и вывести .

    А ты что привел ?

    Reply
  79. I_G_O_R

    (78) смотри картинку, почти тоже самое как в статье, только период наоборот

    Reply
  80. Ish_2

    Не-а. Я растерялся и так и не нашелся (79).

    Давай-ка сам где у тебя что ? Зачем ты складываешь конечные остатки по каждому документу ? Посмотри еще раз (69) и найди 10 отличий

    Reply
  81. I_G_O_R

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

    Reply
  82. Ish_2

    (80) Мы друг друга не понимаем и каждый говорит о чем то своем.

    Контрагент Вася Пупкин имеет долг 100 рублей

    Ему были отпушены две последние накладные

    Накл 1 на 40 р.

    накл 2 на 70 р.

    Нужно получить таблицу

    Контрагент Долг

    Вася Пукин                     100 р.
    Накл 1                         40р.
    Накл 2                         60р.

    Т.е список неоплаченных накладных .

    Reply
  83. I_G_O_R

    (81)я вообще-то смотрю в статью 😮


    Реализация товаров и услуг №1 500р 2200р

    Реализация товаров и услуг №2 1000р 1700р

    Платежное поручение исходящее №1 -500р 700р

    Реализация товаров и услуг №3 1200р 1200р

    а в (69) это я скачал отчет из (44) и сформировал отчет, в чем смысл этого отчета, где там сумма нарастающим итогом, и зачем так много кода я так и не понял.

    Reply
  84. I_G_O_R

    (82) а какое это имеет отношение к нарастающим итогам?

    Reply
  85. Ish_2

    (84) А такое :

    См. текст запроса в статье :

    Вначале мы найдем при помощи запроса таблицу

    Документ Сумма НарастающийИтог

    Накл1           40                     40
    Накл 2          70                     110

    Затем исхитримся и опять запросом сраниваем долг 100 с колонкой накопленные итоги , «попадем » на накл 2 отбросим 10 рублей и запишем

    Накл1           40
    Накл 2          60  
    Reply
  86. Ish_2

    Напиши запрос , чтобы из таблицы

    01.01.09 Накл 1 10

    01.02.09 накл 2 20

    01.03.09 накл 3 30

    Получить нарастающие итоги :

    01.01.09 Накл 1 10 10

    01.02.09 накл 2 20 30

    01.03.09 накл 3 30 60

    И все поймешь.

    Reply
  87. I_G_O_R

    (86) а в скриншоте из (79) разве не оно?

    Reply
  88. Ish_2

    (87) Нет.

    Еще раз. на 100 рублей долга нужно набрать накладных , которые были отпущены клиенту .

    И сказать : вот вам список накладных, которые клиентом не оплачены.

    Из этого списка неолаченных накладных мы выбираем по дате те накладные которые отстоят от текущей даты на компе более чем на N дней суммируем их и говорим — а вот это просроченный долг !

    N — разрешенной количество дней просрочки долга.

    Reply
  89. anig99

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

    Reply
  90. I_G_O_R

    (88) мне интересно, где это в статье написано?

    а во-вторых в отчете из 44 выводится Регистратор, объясните мне как может получится, что долг у контрагента 100 рублей, а у документов сумма 70 и 40? Или этот отчет тоже не решает этой задачи?

    Reply
  91. Ish_2

    (90) Хорошо вот тебе полная картина

    Вася Пупкин Долг 100

    Имеет документы :

    Накл. 1   40
    Накл  2   70
    Платеж  -10       

    Нужно узнать какие накладные клиентом не оплачены и на какую сумму каждая накладная не оплачена (см. (85) вторая таблица) ?

    И ты получишь :

    Накл1           40
    Накл 2          60  
    Reply
  92. Ish_2

    (89) Саш, ты нам только мешаешь ! 😀

    Reply
  93. I_G_O_R

    (91) если решать твоим способом, то таблица ОстаткиИОбороты(хотя кто его знает) не поможет, но задачка интересная. В принципе, чем-то похоже на отчет из УТ «ПродажиПоОплате», только там наоборот выводятся полностью оплаченные.

    Reply
  94. Ish_2

    (93)Интересная в том смысле что :

    1. База у Саши 120Гб.

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

    3. Самое смешное в том , что сейчас я понимаю , что он прав.

    И я готов отказаться от своих предложений как неоптимальных.

    Эти предложения предполагают кодинг.

    Reply
  95. Ish_2

    Саша , ты меня уговорил . Буду писать статью

    «Подведем итоги . Нарастающие.» — о том каким должен быть текст оптимального запроса в данной задаче . В статье — Текст запроса и сопровождающие его иллюстрации в виде таблиц.

    Приглашаю быть злобным оппонентом. Приглашаю также Игоря и Артура.

    Через 2-3 дня сообщу дату публикации.

    Reply
  96. artbear

    (95) Жду

    Reply
  97. Ish_2

    (99),(98),(93) Публикация будет доступна 25.11.09 в 10-00

    Подведем итоги . Нарастающие.

    http://infostart.ru/public/61295/

    Reply
  98. anig99

    (100) а то я в новостях увидел, а прочитать не успел

    Reply
  99. Ish_2

    (101) На сайте что-то происходит. Очередные трудности движка.

    Reply

Leave a Comment

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