Silver¶
В данном разделе приведены сведения о Silver, плагине для СУБД Picodata.
Picodata Enterprise
Функциональность плагина доступна только в коммерческой версии Picodata.
Общие сведения¶
Silver — это модуль расчета себестоимости для распределенной высокопроизводительной базы данных Picodata.
Описание алгоритма расчета и распределения затрат¶
Расчет реализован в виде алгоритма над графом, где каждая вершина представляет собой центр возникновения затрат (узел расчета), а грани — отнесение части затрат на другой центр в соответствии с коэффициентом распределения. Ввиду того, что чаще всего в таком графе существуют циклические зависимости (когда затраты узла расчета 1 распределяются на узел расчета 2, а затраты узла расчета 2, в свою очередь, распределяются на узел расчета 1, напрямую либо через несколько промежуточных узлов расчета), распределение затрат осуществляется в ходе последовательных итераций. Критерием остановки расчета может служить:
- достижение заданного лимита итераций
- уменьшение общей суммы затрат к распределению на очередной итерации до суммы приемлемой общей погрешности
- уменьшение суммы входящих затрат для одного узла расчета до суммы приемлемой погрешности для узла
Так как данные для расчета распределены между отдельными инстансами СУБД Picodata, то выполнение итераций производится параллельно, что позволяет ускорить общее время расчета. При этом, результаты отдельной итерации записываются в таблицу промежуточных результатов.
Начальные данные¶
Начальные данные объединяются в наборы, что позволяет хранить (и обрабатывать) данные для нескольких сценариев. Данные состоят из базы распределения и начальных входящих затрат, которые хранятся в следующих таблицах:
Наборы данных¶
N | Поле | Тип | Описание |
---|---|---|---|
1 | set_id | uuid | идентификатор набора данных |
2 | name | string | наименование набора данных |
3 | year | unsigned int | год периода данных |
4 | month | unsigned int | месяц периода данных |
База распределения¶
N | Поле | Тип | Описание |
---|---|---|---|
1 | id | string | идентификатор записи |
2 | set_id | uuid | идентификатор набора данных |
3 | sender_id | string | узел-отправитель |
4 | receiver_id | string | узел-получатель |
5 | prod_id | string | код продукции (услуги, работы) |
6 | base_value | decimal | значение для получателя |
Начальные затраты¶
N | Поле | Тип | Описание |
---|---|---|---|
1 | id | string | идентификатор записи |
2 | set_id | uuid | идентификатор набора данных |
3 | receiver_id | string | узел-получатель затрат |
4 | cost_type | string | код затраты |
5 | cost_sum | decimal | сумма затраты |
Этапы выполнения алгоритма¶
Подготовка к расчету — создание узлов расчета¶
Перед запуском расчета для каждого узла собирается база распределения из соответствующей таблицы. При этом считается общее значение базы (OCB) и суммируется значение базы по каждому коду продукции (услуге, работе) (формула 1):
где i — порядковый номер кода продукции (услуги, работы) (далее — код выпуска),
\(СВ_i\) — сумма значений базы распределения (выпуска) этого кода продукции (работы, услуги), вычисляется по формуле 2:
где j — порядковый номер получателя кода выпуска,
\(В_j\) — значение для получателя.
Итеративное распределение затрат¶
На каждой итерации расчета в каждом узле выполняются следующие действия:
-
выбираются входящие затраты (для первого шага — из таблицы начальных затрат, для следующих — из соответствующей текущей итерации таблицы промежуточных результатов)
- если задана сумма приемлемой погрешности для узла и общая сумма входящих затрат меньше этого значения, то распределение затрат не выполняется и расчет для узла считается завершенным
- иначе для каждого кода затраты:
- задаются начальные значения для распределения по кодам выпуска:
- \(СРЗ\) (сумма распределяемой затраты), равная сумме затраты и
- \(БРЗ\) (база распределения затраты), равная \(ОСВ\) из формулы 1;
-
для каждого кода выпуска вычисляется часть затраты к распределению на выпуск (\(СЗВ\)):
если \(БРЗ\) равно \(СВ\) текущего кода выпуска из формулы 2, то (формула 3):
\[ СЗВ = СРЗ \]иначе (формула 4):
\[ СЗВ = { СРЗ \over БРЗ } * СВ \]После этого (формула 5):
\[ СРЗ = СРЗ - СЗВ \]и (формула 6):
\[ БРЗ = БРЗ - СВ \] -
полученное значение \(СЗВ\) распределяется по получателям:
- задаются начальные значения для распределения по получателям:
- \(СРЗП\) (сумма распределяемой затраты по получателям), равная \(СЗВ\), и
- \(БРЗП\) (база распределения затраты по получателям), равная \(В\) из формулы 2 для получателя;
-
для каждого получателя вычисляется часть затраты на получателя (\(СЗП\)):
если \(БРЗП\) равно \(В\) текущего получателя, то (формула 7):
\[ СЗП = СРЗП \]иначе (формула 8):
\[ СЗП = { СРЗП \over БРЗП } * В \] -
полученное значение \(СЗП\) увеличивает накопленную сумму затрат для сочетания “код выпуска” — “код затраты” — “получатель” и промежуточный результат для сочетания “код затраты” — “получатель”
- после окончания распределения затрат накопленные промежуточные результаты сохраняются в соответствующую следующей итерации таблицу.
- задаются начальные значения для распределения по получателям:
По окончании итерации проверяется ее порядковый номер. Если задан лимит на количество итераций и номер текущей итерации достиг его, то расчет считается завершенным.
Также проверяется общая сумма входящих затрат для следующей итерации. Если задана сумма приемлемой общей погрешности и общая сумма затрат меньше этого значения, или нет затрат к распределению на следующей итерации, то расчет считается завершенным.
В противном случае запускается следующая итерация расчета.
Сохранение результатов¶
По окончании расчета каждый узел сохраняет накопленные суммы затрат (для сочетаний “код выпуска” — “код затраты” — “получатель”) в таблицу результатов:
N | Поле | Тип | Описание |
---|---|---|---|
1 | id | string | идентификатор записи |
2 | calc_id | uuid | идентификатор расчета |
3 | sender_id | string | узел-отправитель затрат |
4 | receiver_id | string | узел-получатель затрат |
4 | cost_type | string | код затраты |
6 | prod_id | string | код выпуска продукции (работы, услуги) |
5 | cost_sum | decimal | сумма затраты |