Имя: Пароль:
1C
1С v8
Кэширование
, ,
0 azernot
 
19.01.17
15:02
Реализую задачу расчёта пользовательских данных на основе данных ИБ, произвольных числовых данных по заданным пользователем формулам. При этом в формулах могут использоваться другие ранее определённые формулы практически без ограничения уровней вложенности (без зацикливаения)

В процессе расчёта окончательного результата одна и та же формула может использоваться несколько раз но с разными исходными парметрами.

Например, формула
(+ "Оборот ДДС по клиентам за Январь 2017" (без уточнения)
- "Оборот ДДС по клиентам за Январь 2017" (по статье "Возврат"))
/
(+ "Оборот ДДС по клиентам за Февраль 2017" (без уточнения)
- "Оборот ДДС по клиентам за Февраль 2017" (по статье "Возврат"))

Другая формула
(+ "Оборот ДДС по клиентам за Декабрь 2016" (без уточнения)
- "Оборот ДДС по клиентам за Декабрь 2016" (по статье "Возврат"))
/
(+ "Оборот ДДС по клиентам за Январь 2017" (без уточнения)
- "Оборот ДДС по клиентам за Январь 2017" (по статье "Возврат"))

Легко заметить что составляющие
- "Оборот ДДС по клиентам за Январь 2017" (без уточнения)
- "Оборот ДДС по клиентам за Январь 2017" (по статье "Возврат")
используются несколько раз.

Так вот, в целях ускорения расчёта хочется применить кэширование данных. Ключ кэширования состоит из
- типа данных "Оборот ДДС по клиентам"
- параметров (период ДатаС - ДатаПо)
- Отбора данных (КомпоновщикНастроекКомпоновкиДанных.Настройки.Отбор в ХранилищеЗначения)

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

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

А что бы вы посоветовали?
1 Fragster
 
гуру
19.01.17
15:04
соответствие работает и так
2 Fragster
 
гуру
19.01.17
15:05
еще проще - общий модуль с повторным использованием возвращаемых значений на время вызова
3 azernot
 
19.01.17
15:13
(1) Хм.. Т.е. вот так вот просто, делаю Структуру, помещаю в неё все свои ключи и использую эту структуру в качествте ключа для соответствия?
4 Волшебник
 
модератор
19.01.17
15:27
Насколько я помню, соответствие индексируется для ключей примитивных типов и ссылок.
5 azernot
 
19.01.17
15:28
Простая проверка показала, что к сожалению, не работает.


    СоответствиеКэш = Новый Соответствие;
    МойУИД = Неопределено;
    
    Для А = 1 По 15 Цикл
        
        УИД = Новый УникальныйИдентификатор;
        Если А = МоеЧисло Тогда
            МойУИД = УИД;
        КонецЕсли;
        
        ХЗ = Новый ХранилищеЗначения(УИД);
        СтруктураКлюча = Новый Структура;
        СтруктураКлюча.Вставить("Номер", А);
        СтруктураКлюча.Вставить("ХЗ", ХЗ);
        
        СоответствиеКэш.Вставить(СтруктураКлюча, "ХЗ "+А);
    КонецЦикла;
    
    СтруктураКлюча = Новый Структура;
    СтруктураКлюча.Вставить("Номер", МоеЧисло);
    СтруктураКлюча.Вставить("ХЗ", Новый ХранилищеЗначения(МойУИД));
    
    Значение = СоответствиеКэш.Получить(СтруктураКлюча);
    Если Значение = Неопределено Тогда
        Сообщить("Не найдено!");
    Иначе
        Сообщить(Значение);
    КонецЕсли;

Задаю МоеЧисло = 5
Ожидаю сообщение "ХЗ 5"
Сообщает "Не найдено!"
6 Волшебник
 
модератор
19.01.17
15:28
А ещё есть регистры оборотов с агрегатами
7 azernot
 
19.01.17
15:36
Короче, если использовать в ключе соответствия структуру, даже с одним свойством типа "Число", соответствие по такому ключу значение не возвращает...

(2) Где почитать про такой механизм? Это повторное использование учитывает разные параметры передаваемые в одну и ту же функцию в этом модуле?
8 Волшебник
 
модератор
19.01.17
15:39
(7) используй в качества ключа само число, а не структуру
9 azernot
 
19.01.17
15:42
(8) Это понятно :)
Мне нужно использовать в качестве ключа набор из:
Ссылки,
двух дат,
отбора СКД (даже если его преобразовать в какую-то коллекцию).
10 Волшебник
 
модератор
19.01.17
15:42
(9) Присвой этой байде GUID и сохрани его в строку
11 azernot
 
19.01.17
15:43
(9) А как мне потом гарантированно получить такой же GUID для такого же набора данных?
12 Волшебник
 
модератор
19.01.17
15:44
(11) Сохрани в справочник
13 azernot
 
19.01.17
15:46
(12) :)
Ага, а потом имея на входе набор данных, перебрать по-быстрому этот справочник, и сравнить нужные мне реквизиты?

Это будет тот же поиск по ТЗ перебором, или поиск по каскаду соответствий...
14 cathode
 
19.01.17
16:23
(0) Для хэширования в пределах сеанса без хранения в базе может подойти:


// Возвращает хэш-сумму значения, сравнение которой может заменить сравнение самих значений.
//
// Параметры:
//  Значение - Произвольный - Любое значение.
//
// Возвращаемое значение:
//  УникальныйИдентификатор - Уникальный идентификатор, соответствующий MD5-хэшу значения.
//
Функция ХэшЗначения(Значение)
    
    Перем Хэширование, Хэш, Пара;
    
    Хэширование = Новый ХешированиеДанных(ХешФункция.MD5);
    Хэширование.Добавить(ЗначениеВСтрокуВнутр(Значение));
    
    // Корректный вариант преобразования в HEX-строку:
    //Хэш = ФабрикаXDTO.Создать(ФабрикаXDTO.Тип("http://www.w3.org/2001/XMLSchema";, "hexBinary"), Хэширование.ХешСумма).ЛексическоеЗначение;
    
    // Используемый вариант использует недокументированную особенность строкового
    // представления значений ДвоичныеДанные. Работает быстрее, но может сломаться
    // в следующих версиях.
    Хэш = НРег(СтрЗаменить(Хэширование.ХешСумма, " ", ""));
    
    Возврат Новый УникальныйИдентификатор(Сред(Хэш, 1, 8) + "-" + Сред(Хэш, 9, 4) + "-" + Сред(Хэш, 13, 4) + "-" + Сред(Хэш, 17, 4) + "-" + Сред(Хэш, 21, 12));
    
КонецФункции


Если нужен хэш нескольких значений, передавать их в виде массива (или фиксированного массива, большой разницы нет). Структуру использовать нельзя, т.к. результат ЗначениеВСтрокуВнутр() зависит от порядка добавления элементов. Фиксированная структура сериализуется всегда одинаково.
15 Волшебник
 
модератор
19.01.17
16:25
(13) Это говорит о том, что ты кэшируешь какую-то фигню
16 azernot
 
19.01.17
16:32
(14) О, спасибо огромное! Идея в общем-то та же, но в таком готовом виде, под ключ, дорогого стоит.

(15) Ну да, вопрос не прост.
17 azernot
 
19.01.17
16:33
(14) Фиксированная структура, имеется в виду, все элементы которой добавляются в одинаковом порядке?
18 azernot
 
19.01.17
16:34
+(17) А, прям отдельный тип коллекции.. понятно.
19 cathode
 
19.01.17
16:37
(16) Не за что.
Нужно учесть, что тестировалось только в случае, когда значения для хэширования имеют примитивные типы.
У Структуры сериализация пляшет, у ТаблицыЗначений тоже.
20 azernot
 
19.01.17
16:42
(19) я протестировал вот так

    СоответствиеКэш = Новый Соответствие;
    МойУИД = Неопределено;
    
    Для А = 1 По 15 Цикл
        
        УИД = Новый УникальныйИдентификатор;
        Если А = МоеЧисло Тогда
            МойУИД = УИД;
        КонецЕсли;
        
        ХЗ = Новый ХранилищеЗначения(УИД);
        //ХЗ = УИД;
        СтруктураКлюча = Новый Структура;
        СтруктураКлюча.Вставить("Номер", А);
        СтруктураКлюча.Вставить("ХЗ", ХЗ);
        
        
        СоответствиеКэш.Вставить(ХэшЗначения(СтруктураКлюча), "ХЗ "+А);
    КонецЦикла;
    
    СтруктураКлюча = Новый Структура;
    СтруктураКлюча.Вставить("Номер", МоеЧисло);
    ХЗ = Новый ХранилищеЗначения(МойУИД);
    //ХЗ = МойУИД;
    СтруктураКлюча.Вставить("ХЗ", ХЗ);
    
    Значение = СоответствиеКэш.Получить(ХэшЗначения(СтруктураКлюча));
    Если Значение = Неопределено Тогда
        Сообщить("Не найдено!");
    Иначе
        Сообщить(Значение);
    КонецЕсли;


Задаю МоеЧисло = N
Ожидаю сообщение "ХЗ N"
Сообщает "ХЗ N!"