Сергей

4770
Рейтинг
+4 за сутки

Сергей
ildarovich



  •   Регистрация: 19.04.2008 (8 лет назад)

  •   Был(а) на сайте: сегодня в 13:07


Группы

Профессиональный разработчик

Рейтинг 4770

Публикации

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


Битовые строки могли бы упростить реализацию некоторых алгоритмов на языке платформы «1С: Предприятие 8». Но пока в платформе операций с битовыми строками нет. В то же время уже сделанные попытки смоделировать эти операции преобразованиями над числами опираются на циклы обработки отдельных битов, что плохо сказывается на скорости их работы. Предлагается новое простое решение, основанное на представлении битовых строк строками символов «0» и «1». Приводится примеры кода выполнения основных логических операций AND, OR, XOR, NO без использования циклов. В качестве прикладной задачи рассмотрено получение последовательных значений кода Грэя, который можно использовать для ускорения перебора вариантов.


В большинстве широко известных решений для генерации числовой последовательности в запросе порядок длины последовательности должен быть определен при написании текста запроса. Это вызывает определенные трудности при его модификации. Предлагается решение, свободное от этого недостатка. Решение ориентировано на модификацию запроса с использованием объекта "схема запроса".


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


Следующая серия "минимализмов" [http://infostart.ru/public/306536/]. Также, как и в предыдущей статье, здесь приведена подборка коротких оригинальных решений некоторых задач. Ранее эти решения были разбросаны по моим комментариям к чужим публикациям.


Предлагается отчет на основе системы компоновки данных для выявления нарушений последовательности нумерации документов. Применяются методы из статей "Выразить строку как число и строку как дату в запросе" [http://infostart.ru/public/170336/] и "Быстрое определение интервалов в запросе" [http://infostart.ru/public/402534/]. Это позволяет решить задачу быстро и непосредственно в запросе.


В статье описывается новый метод определения интервалов между данными различных записей в запросе. В отличие от общеизвестного метода, время работы предлагаемого метода зависит от объема данных ЛИНЕЙНО. Это обеспечивает ему значительный выигрыш по быстродействию на больших объемах данных. В качестве иллюстрации возможностей метода приведен отчет, показывающий гистограмму распределения времени между продажами.


Показано, как рассчитать в запросе значение хэш-функции для поля, имеющего тип "строка". Приведены результаты испытаний предложенного приема и несколько примеров его использования при решении конкретных практических задач.


Предлагается новый и более компактный метод преобразования даты и числа в строку в запросе


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


Комментарии

DevЗапросом найти ТЧ документа по ТЗ в качестве параметра#6 13.01.17 16:52
Попробуйте вот так:
Код
ВЫБРАТЬ
   Товары.Номенклатура,
   Товары.Количество
ПОМЕСТИТЬ Эталон
ИЗ
   &Товары КАК Товары
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ РАЗЛИЧНЫЕ
   Товары.Ссылка,
   Товары.Номенклатура КАК Номенклатура,
   Товары.Количество КАК Количество
ПОМЕСТИТЬ ВсеСтроки
ИЗ
   Документ.ЗаказПокупателя.Товары КАК Товары

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ РАЗЛИЧНЫЕ
   ЗаказПокупателя.Ссылка,
   Эталон.Номенклатура,
   Эталон.Количество
ИЗ
   Эталон КАК Эталон,
   Документ.ЗаказПокупателя КАК ЗаказПокупателя
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
   Пары.Ссылка
ИЗ
   (ВЫБРАТЬ
      Пары.Ссылка КАК Ссылка,
      Пары.Номенклатура КАК Номенклатура,
      Пары.Количество КАК Количество,
      КОЛИЧЕСТВО(*) КАК Признак
   ИЗ
      ВсеСтроки КАК Пары
   
   СГРУППИРОВАТЬ ПО
      Пары.Ссылка,
      Пары.Номенклатура,
      Пары.Количество) КАК Пары

СГРУППИРОВАТЬ ПО
   Пары.Ссылка

ИМЕЮЩИЕ
   МИНИМУМ(Пары.Признак) = 2
DevУровни, глубина, прародители, циклы и аналоги запросом#113 23.12.16 12:12
(112) Большое спасибо за информацию, такие отзывы (о практическом применении) очень ценны для меня.

По поводу записи временной таблицы - полностью согласен. Этот фактор обязательно нужно учитывать. Недавно закончил развитие метода ускорения расчета нарастающего итога. Там оказалось, что учет времени записи элементов временной таблицы позволяет выбрать оптимальный размер группировок.
DevУровни, глубина, прародители, циклы и аналоги запросом#111 23.12.16 10:24
(110) А что конкретно не получилось?

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

То есть метод рассчитан все же на выявление длинных связей среди относительно небольшого количества объектов (до нескольких тысяч). И отличается тем, что в процессе работы устанавливает (заодно) все связи, даже те, которые впоследствии могут и не понадобиться.
DevКак в запросе выбрать из справочника несколько случайных элементов?#112 22.12.16 12:17
(111) Да, конечно. Вопрос был задан для привлечения внимания вот к этой публикации: Расчет хэш-функции в запросе . (Пример 3).
Dev"Распределение в запросе" или "избавляемся от перебора"#37 20.12.16 12:55
(32 (33) (34) Не знаю, зачем там что-то прибавлять-вычитать, работает вообще без этого. Вот в этом, чуть более коротком варианте запрос работает для чисел вообще какой угодно разрядности:
Код
ВЫБРАТЬ
   Ячейки.Ячейка,
   СУММА(Слева.Количество) - МИНИМУМ(Ячейки.Количество) КАК КоличествоОт,
   СУММА(Слева.Количество) КАК КоличествоДо
ПОМЕСТИТЬ ЛинейкаЯчеек
ИЗ
   Ячейки КАК Ячейки
      ВНУТРЕННЕЕ СОЕДИНЕНИЕ Ячейки КАК Слева
      ПО (Слева.Ячейка <= Ячейки.Ячейка)

СГРУППИРОВАТЬ ПО
   Ячейки.Ячейка
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
   Товары.Товар,
   СУММА(Слева.Количество) - МИНИМУМ(Товары.Количество) КАК КоличествоОт,
   СУММА(Слева.Количество) КАК КоличествоДо
ПОМЕСТИТЬ ЛинейкаТоваров
ИЗ
   Товары КАК Товары
      ВНУТРЕННЕЕ СОЕДИНЕНИЕ Товары КАК Слева
      ПО (Слева.Товар <= Товары.Товар)

СГРУППИРОВАТЬ ПО
   Товары.Товар
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
   Ячейки.Ячейка КАК Ячейка,
   Товары.Товар КАК Товар,
   ВЫБОР
      КОГДА Товары.КоличествоДо < Ячейки.КоличествоДо
         ТОГДА Товары.КоличествоДо
      ИНАЧЕ Ячейки.КоличествоДо
   КОНЕЦ - ВЫБОР
      КОГДА Товары.КоличествоОт > Ячейки.КоличествоОт
         ТОГДА Товары.КоличествоОт
      ИНАЧЕ Ячейки.КоличествоОт
   КОНЕЦ КАК Количество
ИЗ
   ЛинейкаЯчеек КАК Ячейки
      ВНУТРЕННЕЕ СОЕДИНЕНИЕ ЛинейкаТоваров КАК Товары
      ПО Ячейки.КоличествоОт < Товары.КоличествоДо
         И Ячейки.КоличествоДо > Товары.КоличествоОт

Идея запроса вовсе не в целых числах, а в том, чтобы построить друг против друга линейку товаров и ячеек и найти пересечение отрезков на этих линейках.
Вот в этом обсуждении есть картинка: http://forum.infostart.ru/forum9/topic32459/message361861/#message361861 .
Dev"Распределение в запросе" или "избавляемся от перебора"#31 19.12.16 14:47
(28)(29) Вы очень глубоко заблуждаетесь!

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

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

N Число строк Затрачено миллисекунд
1 1 000 302
2 2 000 998
3 3 000 2 263
4 4 000 3 840
5 5 000 5 971
6 6 000 8 443
7 7 000 12 817
8 8 000 14 846
9 9 000 18 851
10 10 000 23 346

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

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

Что прямо противоречит озвученным вами выводам.

Вот таблица:
N Метод Число строк Затрачено миллисекунд
1 Скрипт 100 8
2 Запрос 100 48
3 Скрипт 200 8
4 Запрос 200 56
5 Скрипт 1000 37
6 Запрос 1000 716
7 Скрипт 2000 75
8 Запрос 2000 2457
9 Скрипт 10000 379
10 Запрос 10000 52873
11 Скрипт 20000 774
12 Запрос 20000 227231

Посмотрите на результат при двадцати тысячах строк: 0,7 секунд для кода против 227(!!!) секунд для запроса.
Для распределения по таблицам значений использовалась взятая из "Минимализмов" (http://infostart.ru/public/306536/) функция (задача 7).

Если захотите перепроверить, вот обработка, которой я пользовался:

Прикрепленные файлы:

ДоказательстваПротивЗапроса.erf
Dev"Распределение в запросе" или "избавляемся от перебора"#23 16.12.16 15:30
Еще один пример того, что новое - это хорошо забытое старое
Вот ссылки:

http://infostart.ru/public/20221/
http://infostart.ru/public/58966/
http://infostart.ru/public/61295/
http://infostart.ru/public/62899/
http://infostart.ru/public/68225/
http://infostart.ru/public/88999/
http://infostart.ru/public/122548/

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

Теперь по сути:

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

Эта задача из-за своей природы запросом решается сложнее.
И может выигрывать либо в специфических случаях небольшого количества строк, либо при применении сложных методов ускорения расчета нарастающего итога.
Из-за того, что используются тэта-соединения (целых три штуки!).
В результате время работы запроса может очень сильно (квадратично) увеличиться с ростом числа "ячеек" и "товаров".

В общем, я против крайностей и "универсальных решений", за более взвешенное и обдуманное решение в каждом конкретном случае.
DevУровни, глубина, прародители, циклы и аналоги запросом#108 12.12.16 11:59
(107) Сомневаюсь, что так можно добиться ускорения. Дело в том, что приведенный запрос, который вы хотите поместить внутрь цикла подбора значения уровня, сам по себе не быстрый. За счет соединения через точку Родитель...Родитель...Родитель для каждого элемента справочника выполняется n неявных соединений, где n - пробная глубина справочника.
В вашем предложении "если взяли мало, то умножаем на 2" означает, что запрос и все неявные соединения в нем выполняются много раз заново. Это очень расточительно. Поэтому метод, предложенный в статье, который решает ту же задачу с использованием в единственном пакетном запросе log2(n) соединений, вместо n соединений, будет работать быстрее.
Вообще выигрыш (при использовании подхода, изложенного в статье) будет чуть меньше n/log2(n), так как потребуется время на запись элементов временных таблиц.
DevМинимализмы 2#74 09.12.16 12:36
(73) Вы правы, в запросе в 29 не хватает последней строчки СГРУППИРОВАТЬ ПО А,Б.
В итоге текст запроса должен выглядеть так:
Код
ВЫБРАТЬ А, Б, КОЛИЧЕСТВО(*) 
ИЗ (ВЫБРАТЬ А, Б ИЗ Дано ГДЕ А <= Б 
       ОБЪЕДИНИТЬ ВСЕ 
       ВЫБРАТЬ Б, А ИЗ Дано ГДЕ А > Б) ВЗ
СГРУППИРОВАТЬ ПО А,Б
DevЗапрос: распределение остатков (интересная задача)#17 08.12.16 17:42
Думаю, помочь должна вот эта статья: http://infostart.ru/public/266377/ .

Хотя там задача более стандартная: требуемое скалярное количество расписывается по остаткам партий.

А у вас исходные данные формируются наоборот: имеющийся скалярный остаток расписывается по требуемым "партиям строк заказа".