Имя: Пароль:
1C
1С v8
Как передать в фоновое задание большую таблицу значений (12 млн записей)
0 Solemn
 
12.11.14
14:24
Добрый день коллеги, пытаюсь с помощью многопоточности ускорить обработку таблицы значений, но встал вопрос как эту таблицу передать в фоновое задание, через параметры если передавать, то пожирается гигов 30 памяти на сервере 1С и повисает, запуска самих заданий не дождался, есть какие идеи?
1 Looser-1c
 
12.11.14
14:26
В файл выгружай
2 Kalambur
 
12.11.14
14:27
(1) там наверно ключевое "ускорить обработку "
3 Господин ПЖ
 
12.11.14
14:28
база на скуле?

такую таблицу проще затолкать в таблицу скуля и обработать там, если она на куски не рубится
4 Solemn
 
12.11.14
14:28
(1) а мысль :)
5 Looser-1c
 
12.11.14
14:28
(3) кстати, вариант...
6 tridog
 
12.11.14
14:30
(0) И кто только придумал эту ересь - передавать огромные ТЗ в параметры фонового задания. Распараллеливают они, ппц

Лучше придумать другой алгоритм "диспетчерзиации" задач между запущенными заданиями. Так, чтобы не требовалось гонять половину базы в оперативной памяти (а это и происходит при передаче параметров фонового задания).
7 Looser-1c
 
12.11.14
14:32
И ещё кстати... Почему не заставить РЗ самому получить эти 12 лямов строк?
8 Solemn
 
12.11.14
14:34
(3) Этот вариант оч. долго согласовывать, и скорее всего не одобрят, плюс доступы на SQL выпрашивать. И не совсем понятно как объектные сущности в таблице значений разложить в таблице SQL много шаманства по моему будет
9 Looser-1c
 
12.11.14
14:34
(8) "Этот вариант оч. долго согласовывать"
Беги оттуда
10 Господин ПЖ
 
12.11.14
14:35
(8) формально он у тебя есть - ты же в базу ходишь как-то
11 Euguln
 
12.11.14
14:35
(7) + резонный вопрос, откуда она взялась, такая табличка.
12 Господин ПЖ
 
12.11.14
14:36
>И не совсем понятно как объектные сущности в таблице значений разложить в таблице SQL много шаманства по моему будет

мы не в курсе накой черт тебе 12 лямов записей
13 Solemn
 
12.11.14
14:41
(12) Мне они не нужны, табличка из типового проведение себестоимости УПП (РАУЗ)
14 Solemn
 
12.11.14
14:44
(7) Если РЗ=ФЗ, то думал об этом, но к сожалению в моей задаче это не сработает
15 vhl
 
12.11.14
14:54
(0) Изначально не выносить с сервера на клиент
16 Solemn
 
12.11.14
14:59
(15) Передается из одной процедуры выполняемом в серверном общем модуле, в фоновое задание, которое то же на сервере выполняется.
17 Локи-13
 
12.11.14
15:05
а что именно запускается в несколько потоков?
18 H A D G E H O G s
 
12.11.14
15:05
(16) Сериализация-десериализация ТЗ способны устроить кошмар любой системе.
19 H A D G E H O G s
 
12.11.14
15:06
Как эта ТЗ формируется? Очень сложно?
20 Зеленый пень
 
12.11.14
15:15
(8) Добавь свой регистр сведений - будет как ТЗ.
21 Господин ПЖ
 
12.11.14
15:16
>Как эта ТЗ формируется? Очень сложно?

запускают чего-то типа расчет себестоимости - и привет
22 МихаилМ
 
12.11.14
15:18
тз ->хз. можно еще попробовать хз в строку внутреннюю.

либо тз с хз и в временный файл.
23 H A D G E H O G s
 
12.11.14
15:21
(22) Хреновое решение.
24 Локи-13
 
12.11.14
15:23
где ТС? что распараллеливается то?
25 Господин ПЖ
 
12.11.14
15:24
было не так давно в одной отраслевой упп...

модуль проведение документа.

внутри два цикла, один в другой вложен

внутри 2-го обход ТЧ и набивание ТЗ построчно...

теперь простая арифметика:

ТЧ = 1000 строк

и каждый счетчик циклов по 100 итераций

ТЗ = 10 000 000 строк

клиент "думает" до 2 Гб и падает
26 H A D G E H O G s
 
12.11.14
15:26
(25) Огласи чемпиона.
27 Господин ПЖ
 
12.11.14
15:29
что делает клиент? звонит во франь, консультант франя заходит по rdp на сервак и (о чудо!) проводит документ. За 10 минут. Сервак 64-бит. А значит 3,5 Гб на клиента скребя ложкой по дну ему хватает.

какой вывод сделал франь?

купите 64-бит сервер 1с...
28 Локи-13
 
12.11.14
15:31
(27) так куплен же. что еще покупать?
29 Господин ПЖ
 
12.11.14
15:33
(28) так дело в том, зайка моя, что от него толку в (25, 27) будет 0 без переписывания кода...
30 Господин ПЖ
 
12.11.14
15:35
у тебя то сервер падает
31 Solemn
 
12.11.14
15:57
(17) Запись движений в базу (сколько строк столько и движений)  :)
32 Solemn
 
12.11.14
15:58
+(31) движений=записей в регистр накопления
33 Лефмихалыч
 
12.11.14
16:12
(0) а нельзя эту ТЗ прямо внутри фонового генерить?
34 Лефмихалыч
 
12.11.14
16:13
+(33) например, в фоновое передавать только организацию, подразделение и там группу какой-нить номенклатуры, а таблицу оборотов (предположим, что речь про обороты) получать из базы уже там
35 Solemn
 
12.11.14
16:22
(33) нет, так как запрос делается по движениям в базе, которые потом либо меняются либо удаляются (после запроса), если один фон начнет менять движения, а второй начнет их только читать перед подготовкой ТЗ, то в итоге они будут работать с разными таблицами значений
36 H A D G E H O G s
 
12.11.14
16:24
(35) Пусть фоны читают ТЗ и ждут, пока все флаги в служебном регистре сведений не установятся в "Можно писать"
37 18_plus
 
12.11.14
16:25
ДЛЯ ИЗМЕНЕНИЯ не годится в этом случае?
38 Solemn
 
12.11.14
16:38
(37) управляемый режим давно уже включен, "ДЛЯ ИЗМЕНЕНИЯ" игнорится, наверное можно управляемую блокировку установить, только по таймауту тож легко вылететь
(36) Наверное в регистр в ресурс с типом ХранилищеЗначения проще положить саму табличку, спасиб за идею с регистром, ща буду пробовать
39 H A D G E H O G s
 
12.11.14
16:44
(38) Нет, не проще.
40 H A D G E H O G s
 
12.11.14
16:45
(38) При положении в ХЗ пойдет сериализация в XDTO + кодирование в base64, которое, я боюсь, выполнено через опу..

При извлечении из ХЗ пойдет обратный процесс.
41 Гёдза
 
12.11.14
16:45
(36) почему флаги, а не блокировки?
42 H A D G E H O G s
 
12.11.14
16:46
(41) На тот невероятный случай, когда один процесс прочтет и запишет данные раньше, чем запустится другой процесс.
43 H A D G E H O G s
 
12.11.14
16:47
(42) Мало ли.
44 КонецЦикла
 
12.11.14
16:48
21-й век на дворе, а все возитесь с таблицами значений?
Пригласите специалиста...
45 ПушЫстый подмышко
 
12.11.14
17:03
(44) А специалист с чем будет возиться?
46 Локи-13
 
12.11.14
17:06
(29) нет, зачем франч предложил купить 64бит сервер, если он уже есть? на который консультант зашел через рдп.
47 Solemn
 
12.11.14
17:11
(41) Пишется и читается вне транзакции, блокировки вообще не сработают, плюс (если делать в транзакции) большая вероятность таймаута
48 H A D G E H O G s
 
12.11.14
17:12
"Пишется и читается вне транзакции"

Это ты так думаешь.
49 Локи-13
 
12.11.14
17:14
(31) распараллеливается запись одного набора?
и в наборе 12 миллионов строк?

что-то я не очень понял...

странно что все пытаются придумать что делать с тз, вместо того, чтобы удостовериться в том, что в принципе выбрана правильная методика решения задачи.
50 H A D G E H O G s
 
12.11.14
17:15
(49) Я думаю -там регистраторов по числу потоков.
51 Волшебник
 
модератор
12.11.14
17:16
(0) накой черт тебе 12 лямов записей?
52 Локи-13
 
12.11.14
17:18
(50) тогда почему нельзя приготовить отдельные наборы с меньшим числом записей на базе этой таблицы, и передавать уже их?
53 Лефмихалыч
 
12.11.14
17:21
(35) разбей данные на не пересекающиеся куски и читай-пиши, сколько угодно и когда угодно
54 Лефмихалыч
 
12.11.14
17:26
Короче, вот тут описано, как это (0) надо делать
http://infostart.ru/public/191786/
map/reduce в чистом виде. Иначе ни какого ускорения не получится и вся параллельность будет валиться на блокировках
55 Solemn
 
12.11.14
17:34
(51) Мне то они не нужны, типовой расчет себестоимости в упп 1.3, по методологии расчета вопрос тож не ко мне, не я ее утверждал.
56 tridog
 
12.11.14
17:38
(40) XDTO тут не причем, это другая сериализация)
57 Solemn
 
12.11.14
17:43
(40) Да, не получилось в ХранилищеЗначения в рег. сведений поместить, 200 тыс. записей легко прошли сек. за 20, а на 5 млн отвалилось по ошибке потока (
58 Solemn
 
12.11.14
17:48
+(57) через 15 минут отвалилось
59 H A D G E H O G s
 
12.11.14
17:51
(56) Проверял?
60 tridog
 
12.11.14
17:51
(58) Вы пытаетесь сделать какое-то "еврейское" распараллеливание - думаю, что ничего у Вас не выйдет. Предполагаемая модель для распределения задач по "потокам" - убога и нежизнеспособна.
Вместо того, чтобы пытаться с помощью "молотка и такой-то матери" как-то передать ТЗ "потоку" - гораздо перспективней будет подойти к вопросу с другой стороны.
Проанализировать алгоритм, определить на какие атомарные операции его можно разбить - и уже от этого "плясать"
61 tridog
 
12.11.14
17:54
(59) Угумс. Типы, не имеющие XDTO-сериализации - прекрасно помещаются в хранилище значения. Есть и обратные примеры - когда тип помещается в хранилище, но не имеет XDTO-сериализации.

Исследования методом "научного тыка" показали, что, помещение в хранилище значения - эквивалентно ЗначениеВСтрокуВнутр(), а не XDTO-сериализации.
62 H A D G E H O G s
 
12.11.14
17:54
(60) Все такие умные, что ППЦ.

Ну, разбей хотя бы алгоритм удаления движений по нескольку регистров на поток - заипешься код писать, а потом (самое главное) ошибки ловить. Это примитив.

А мы тут про расчет себестоимости.
63 tridog
 
12.11.14
17:54
+(61) Обратные примеры - когда тип имеет XDTO-сериализацию, но в хранилище значения не помещается. Очепятался
64 H A D G E H O G s
 
12.11.14
17:54
(61) ТЗ имеет XDTO сериализацию.
65 tridog
 
12.11.14
17:56
(62) Многопоточность это вообще сложно.
(64) И что? Есть типы, которые ее не имеют - но в хранилище помещаются. И наоборот, есть типы которые не помещаются в хранилище, но пишутся в XDTO
66 H A D G E H O G s
 
12.11.14
17:56
(61)
Исследования методом "научного тыка" показали.

Что делалось?
67 Локи-13
 
12.11.14
17:58
(61) вроде как эту штуку пофиксили в 8.3
68 tridog
 
12.11.14
17:59
(66) Вкратце - перебирались почти все типы встроенного языка (вплоть до ОбъектМетаданных, ИсторияРаботыПользователей, РасширенноеИмяXML - и прочего безобразия).

Для каждого типа делалась попытка:
1. Поместить в хранилище значения
2. СериализаторXDTO.ЗаписатьXML
3. ЗначениеВСтрокуВнутр

Совпадение между 1 и 3 - 100%
Между 1 и 2 - сильно меньше
69 H A D G E H O G s
 
12.11.14
18:01
(68) Масштабно, епта.
Результаты опубликуй.

ТЗ В XDTO есть? Нет? А если найду?!
70 tridog
 
12.11.14
18:02
(69) Если найду - опубликую.
Еще выяснилось, что просто ЗаписатьXML() - который метод глобального контекста - тоже сильно разнится с СериализаторXDTO.ЗаписатьXML().

ТЗ в XDTO есть :) Но это не значит, что помещение в хранилище значения - есть XDTO
71 H A D G E H O G s
 
12.11.14
18:04
(70)
ЗаписатьXML() - который метод глобального контекста - тоже сильно разнится с СериализаторXDTO.ЗаписатьXML().

of course!

ЗаписатьXML() сериализует в XML
СериализаторXDTO.ЗаписатьXML() сериализует в XDTO
72 tridog
 
12.11.14
18:08
(71) Это имеет не очень не много смысла.
Подозреваю, что просто ЗаписатьXML() от 8.0 остался, пока XDTO не было.
73 Serginio1
 
12.11.14
18:20
(0) Я через  выгружал в текстовый файл и булками загружал во временную таблицу.
(71) Ты случайно с ЗаписатьXDTO  не путаешь?
74 H A D G E H O G s
 
12.11.14
18:30
(68) Дааа, ты чертовски прав..
1) Создал справочник с реквизитом ХЗ.
2) Выполнил код

    Запрос=Новый Запрос;
    Запрос.Текст=
    "ВЫБРАТЬ ПЕРВЫЕ 10
    |    Номенклатура.Ссылка,
    |    Номенклатура.Артикул,
    |    Номенклатура.Весовой
    |ИЗ
    |    Справочник.Номенклатура КАК Номенклатура";
    ТЗ=Запрос.Выполнить().Выгрузить();
    ЭтотОбъект.Реквизит1=Новый ХранилищеЗначения(ТЗ);
3) Записал.
4) В SQL -е этот реквизит (image поле) выгрузил в файл.
5) Там даже не в base64, а тупо текст.

{0,"Ссылка",
{"Pattern",
{"L"},
{"#",dd0e8719-5e55-43a0-944a-8321d4c46843}
},"Ссылка",25},
{1,"Артикул",
{"Pattern",
{"S",25,1},
{"L"}
},"Артикул",25},
{2,"Весовой",
{"Pattern",
{"B"},
{"L"}
},"Весовой",2}
},
{2,3,0,0,1,1,2,2,
{1,10,
{2,0,3,
{"#",dd0e8719-5e55-43a0-944a-8321d4c46843,124:8019001517615d5d11dfdff551bb732a},


Простите за кодировку, было лениво морочиться.
75 H A D G E H O G s
 
12.11.14
18:30
Это печально.
76 H A D G E H O G s
 
12.11.14
18:31
Млядские строки, неужели нельзя в ХЗ сохранять кусок памяти.
77 MM
 
12.11.14
18:41
(76) Так там не один кусок памяти, а набор объектов (строки ТЗ, колонки) содержащих друг на друга, наверно. Может стоит указать объект СжатиеДанных?
78 Serginio1
 
12.11.14
18:55
(76) Кстати а как насчет использования ЗаписьFastInfoset
79 Serginio1
 
12.11.14
18:59
78 Типа такого
Функция ПоместитьОбъектВХранилище(Источник)
    ЗаписьXML = Новый ЗаписьFastInfoset;
    ЗаписьXML.УстановитьДвоичныеДанные();
    ЗаписьXML.ЗаписатьОбъявлениеXML();
    ЗаписатьXML(ЗаписьXML, Источник, НазначениеТипаXML.Явное);
    ДвоичныеДанные = ЗаписьXML.Закрыть();
    Возврат Новый ХранилищеЗначения(ДвоичныеДанные, Новый СжатиеДанных(9));
КонецФункции
80 tridog
 
12.11.14
19:18
(76) Вот тут я конечно тот еще басист - но что-то мне подсказывает, что если просто сохранять кусок памяти - то его потом будет оооочень сложно прочитать следующей версией, когда в плюсовом классе будет изменен состав членов.

Например, в той же Java - если сделать implements Serializable и не реализовывать свои writeObject и readObject - то именно так и получится. А если реализовывать writeObject и readObject - то это уже не будет "просто кусок памяти".
81 tridog
 
12.11.14
19:19
(79) Все равно будет строка.
В которую будут преобразованы двоичные данные :)
82 МихаилМ
 
12.11.14
19:39
(74)
Вы забыли указать степень сжатия при создании хранилища.
83 Serginio1
 
12.11.14
20:10
(80) Сериализация разная бывает. Есть по аналогии с Базой Данных с разруливанием циклических ссылок. Например
https://ru.wikipedia.org/wiki/Protocol_Buffers
84 Serginio1
 
12.11.14
20:13
85 tridog
 
12.11.14
20:31
(83) protobuf, как и json - всего-лишь форматы. Ничего нового в такое понятие как сериализация они не приносят.

К тому же, даже из вашей ссылки на вики:

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

> Protocol Buffers не предназначен для чтения пользователем
> и представляет собой двоичный формат. Для десериализации
> данных необходим отдельный .proto-файл, в котором
> определяется формат сообщения.

Т.е. опять-таки нет речи о том, чтобы просто взять кусок оперативной памяти и зафигачить в файл (а потом просто прочитать из файла).

На основании объекта класса строится DTO-представление, которое уже и пишется файл.
86 arsik
 
гуру
12.11.14
20:32
(0) ИМХО - Все намного проще делается.
Не лучше все движения запихнуть во временную таблицу с полем порядковый номер. И забирать уже из временной по условию (от 1 до милиона) - первый поток, от милиона+1 до двух милионов - второй поток и тд.
87 tridog
 
12.11.14
20:39
(86) Для этого всего-лишь нужно умудриться передать в другой сеанс менеджер временных таблиц)
88 Solemn
 
12.11.14
20:40
(86) Каким же образом из разных сеансов (фоновых заданий) получать временную таблицу созданную в родительском сеансе?
89 arsik
 
гуру
12.11.14
20:45
(87) Через хранилище разве нельзя? И Запрос и МВТ
90 H A D G E H O G s
 
12.11.14
21:17
(89) Только не в 8.3
91 H A D G E H O G s
 
12.11.14
21:18
(77) Куски памяти, неважно.
92 H A D G E H O G s
 
12.11.14
21:19
(82) Я не сомневался в тебе. Сжатие данных скорее всего сожмет эту строку deflate-ом.
93 Serginio1
 
12.11.14
21:23
(85) Если это массив структур то можно взять и кусок памяти, так как они храняться все в одном непрерывном куске.
Что касается объектов, то они разбросаны по всей памяти.
Таблица типизирована, то можно записывать как в DBF для данных с определенным размером либо указывая размер данных в первых байтах например для строк.
Либо записывать в аналог иерархической бд
94 H A D G E H O G s
 
12.11.14
21:27
(93) Я не соглашусь с тобой.
Имхается мне, что все объекты в 1С - связные списки (даже массивы и структуры) - нет падения скорости вставки на больших объемах.
95 К_Дач
 
12.11.14
21:27
Мегазадача... а если попробовать как-то получать из разных сеансов адрес ячеек в ОЗУ, занятых исходной таблицей (которую инициировал родительский сеанс)?

http://rsdn.ru/article/cpp/ObjectsAndPointers.xml
96 H A D G E H O G s
 
12.11.14
21:28
(95) Аххх, если бы узнать адреса объектов 1С... мммм, какие возможности, но. Мечты. мечты.
97 Serginio1
 
12.11.14
21:29
(88)Есть глобальные временные таблицы
http://msdn.microsoft.com/ru-ru/library/ms174979.aspx
Временные таблицы


Можно создавать локальные и глобальные временные таблицы.  Локальные временные таблицы видимы только во время текущего сеанса, а глобальные — во всех сеансах. Временные таблицы не подлежат секционированию.

Имени локальной временной таблицы должен предшествовать знак номера (#table_name), а имени глобальной временной таблицы — двойной знак номера (##table_name).  

Инструкции SQL могут обращаться к временной таблице по заданному в инструкции CREATE TABLE значению аргумента table_name, например:
98 H A D G E H O G s
 
12.11.14
21:30
(97) Ты разбирался в тем, что такое
Protocol Buffers
99 Serginio1
 
12.11.14
21:30
(94) Так и на массивах с капасити с увеличение объема в 2 раза ты этого не увидишь. В Net все списки такие масиивы с запасом.
100 H A D G E H O G s
 
12.11.14
21:31
(98) По мне сериализация в Protocol Buffers - это полная аналогия записи в файл области памяти из Record.
101 H A D G E H O G s
 
12.11.14
21:32
(99) Не понял твоих мыслей. Мы говорим о динамическом массиве?
102 Serginio1
 
12.11.14
21:32
(98) Нет, но я сам когда то делал иерархическую БД на Delphi http://files.rsdn.ru/19608/C1InDelphi.zip
103 Serginio1
 
12.11.14
21:33
(101) Посмотри реализацию List
104 H A D G E H O G s
 
12.11.14
21:34
(102) Я тоже делал, делал. Связные двухсторонние списки, динамическая загрузка страниц из файла. Послал нахер, когда стал разбираться с индексами.
105 H A D G E H O G s
 
12.11.14
21:34
(104) Все сам, голый код, никаких BDE.
106 К_Дач
 
12.11.14
21:34
(97) что толку от ВТ, если 12 млн записей вешают сервер СУБД?

Единственное, можно попробовать передавать по кускам, например по 1 млн записей по схеме:

Передать в ВТ;
Выбрать из ВТ на сервере, объединить с ВТ_Буфер;
Очистить ВТ;

Передать в ВТ и т.д.
107 H A D G E H O G s
 
12.11.14
21:35
(103) Я надеюсь, это связный список.
108 К_Дач
 
12.11.14
21:37
(97) кстати, ты в курсе, что глобальная ВТ жива на сервере СУБД только до тех пор, пока жив (не отвалился) сеанс, ее создавший?
109 H A D G E H O G s
 
12.11.14
21:37
(107) Ах тыж млять, динамический массив,

array of Pointer;
110 H A D G E H O G s
 
12.11.14
21:37
Они охренели?
111 tridog
 
12.11.14
21:38
(100) см (85). Нет там "записи в файл области памяти"
112 H A D G E H O G s
 
12.11.14
21:40
(111) Ты не понял, что я спросил :-)
113 Solemn
 
12.11.14
21:50
(97)я в курсе про глобальную ВТ, но ее не создать средствами 1С, напрямую обращаться к серверу субд прав нет
114 К_Дач
 
12.11.14
21:58
(113) посмотри, может тебе поможет. я делал хранимку и вызывал ее из 1С, а хранимка рулила глобальной ВТ

http://infostart.ru/public/287772/
115 Serginio1
 
12.11.14
22:27
(109)
[__DynamicallyInvokable]
public void Add(T item)
{
    if (this._size == this._items.Length)
    {
        this.EnsureCapacity(this._size + 1);
    }
    this._items[this._size++] = item;
    this._version++;
}


private void EnsureCapacity(int min)
{
    if (this._items.Length < min)
    {
        int num = (this._items.Length == 0) ? 4 : (this._items.Length * 2);
        if (num > 0x7fefffff)
        {
            num = 0x7fefffff;
        }
        if (num < min)
        {
            num = min;
        }
        this.Capacity = num;
    }
}


Это стандарные динамические массивы, StringBuilder итд с излишним объемом и увеличением в 2 раза при полном заполнении.
116 Serginio1
 
12.11.14
22:28
110 кстати посмотри что записывает ЗаписьFastInfoset
117 H A D G E H O G s
 
12.11.14
22:31
(116) Двоичные данные, а что?
118 H A D G E H O G s
 
12.11.14
22:32
(116) Что-то закодированное в base64
119 arsik
 
гуру
12.11.14
22:49
(90) а тс уже сознался, что у него 8.3? Если 8ю3 то там еще проще, в одном сеансе асинхронным методом запустить несколько процедур.
(106) ничего они не вешают. это тз вешает.
(108) про ком соединения тоже такой слух ходил, но ничего, через хранилище работает.
120 Serginio1
 
12.11.14
22:50
Ну двоичные данные можно посмотреть и блокнотом в нужной кодировке. Во всяком случае строки можно и прочитать,
121 tridog
 
12.11.14
22:53
(119) Прошу пример "в одном сеансе асинхронным методом запустить несколько процедур"
122 Serginio1
 
12.11.14
22:57
(108) http://technet.microsoft.com/ru-ru/library/ms186986(v=sql.105).aspx

Существует два вида временных таблиц: локальные и глобальные. Локальные временные таблицы видны только их создателям до завершения сеанса соединения с экземпляром SQL Server, как только они впервые созданы или когда на них появляется ссылка. Локальные временные таблицы удаляются после отключения пользователя от экземпляра SQL Server. Глобальные временные таблицы видны всем пользователям в течение любых сеансов соединения после создания этих таблиц и удаляются, когда все пользователи, ссылающиеся на эти таблицы, отключаются от экземпляра SQL Server.


Другое дело, что сессию нужно держать пока другая сессия не подключится к этой таблице
123 arsik
 
гуру
12.11.14
23:07
(121) В последних стандартных все примеры.
124 tridog
 
12.11.14
23:08
(123) В типовых нет ни одного примера "в одном сеансе асинхронным методом запустить несколько процедур". Приведи хотя бы один, пожалуйста :)
125 DrZombi
 
гуру
13.11.14
06:30
(0) Передавать, через ВременноеХранилище :)
126 MM
 
13.11.14
09:46
(91), (95) Важно, только сейчас сообразил сервер 1С даже под Виндовс может быть 32 и 64, а значит разная структура, как минимум, указателей в этой памяти. А ещё Линукс есть и всё должно быть совместимо в одном кластере.
(94) А как в связном списке эффективно обращаться по индексу? Думаю там более сложная структура хранения.
(121) Скорее всего он говорит об оповещениях, но они работают в одном потоке.
127 Serginio1
 
13.11.14
10:10
(126) Типа дерева
http://rsdn.ru/forum/src/450320
128 arsik
 
гуру
13.11.14
10:11
(126) Если честно - детально вопрос не изучал. Но разве нельзя открыть одновременно 5 форм. В которых при открытии вызвать оповещение вопрос таймаутом у которого обработчикзавершения будет искомая процедура?
129 MM
 
13.11.14
10:22
(127) только не бинарное думаю.
(128) так там однопоточная обработка. Объектов синхронизации в языке ведь нет.
130 arsik
 
гуру
13.11.14
10:46
(129) А вот так?

ПоказатьПредупреждение(Новый ОписаниеОповещения("НовыйОбработчикЗавершение", ЭтотОбъект),"Текст",10);
ПоказатьПредупреждение(Новый ОписаниеОповещения("НовыйОбработчикЗавершение1", ЭтотОбъект),"Текст",10);
ПоказатьПредупреждение(Новый ОписаниеОповещения("НовыйОбработчикЗавершение2", ЭтотОбъект),"Текст",10);
131 Serginio1
 
13.11.14
11:03
(117) Посмотрел, что там делает запись в ЗаписьFastInfoset

Правда при записи Тз нужно использовать СериализаторXDTO явно

Функция ПоместитьОбъектВХранилище(Источник)
    ЗаписьXML = Новый ЗаписьFastInfoset;
    ЗаписьXML.УстановитьДвоичныеДанные();
    ЗаписьXML.ЗаписатьОбъявлениеXML();

    СериализаторXDTO.ЗаписатьXML(ЗаписьXML, Источник);
    ДвоичныеДанные = ЗаписьXML.Закрыть();
    возврат  ДвоичныеДанные
КонецФункции


Тз=Новый ТаблицаЗначений;
    Колонки=Тз.Колонки;
    Колонки.Добавить("Поле1",Новый ОписаниеТипов("Строка"));
    Колонки.Добавить("Поле2",Новый ОписаниеТипов("Строка"));
    
    Для сч=1 По 1000 Цикл
    
        Стр=Тз.Добавить();
        Стр.Поле1="F1-"+Сч;
        Стр.Поле2="F2-"+Сч;
    
    КонецЦикла;
    тз.ВыбратьСтроку();
    
    Стр=ЗапистьОбъектВXML(тз);
    Сообщить(СтрДлина(стр));
    
    
    ДД=ПоместитьОбъектВХранилище(Тз);
    Сообщить(дд.Размер());
    дд.Записать("C:\ЗаписьFastInfoset");

Посмотрел на это чудо и увидел, что между полями 8 байтов.
Понятно, что нужно перед записью строки записать длину. В Net например для этого используется
132 Serginio1
 
13.11.14
11:05
protected void Write7BitEncodedInt(int value)
{
    uint num = (uint) value;
    while (num >= 0x80)
    {
        this.Write((byte) (num | 0x80));
        num = num >> 7;
    }
    this.Write((byte) num);
}


И чтение
protected internal int Read7BitEncodedInt()
{
    byte num3;
    int num = 0;
    int num2 = 0;
    do
    {
        if (num2 == 0x23)
        {
            throw new FormatException(Environment.GetResourceString("Format_Bad7BitInt32"));
        }
        num3 = this.ReadByte();
        num |= (num3 & 0x7f) << num2;
        num2 += 7;
    }
    while ((num3 & 0x80) != 0);
    return num;
}

что сокращает количество байтов для записи длины строки
133 Reaper_1c
 
13.11.14
11:18
(13) Ты пробовал использовать даты запрета редактирования и проведение вне транзакции?
134 tridog
 
13.11.14
11:22
(130) О господи... Сам то проверял?
В один поток выполняться будет.

Зато сколько бреда уже видел на форумах, что в 8.3 сделали многопоточность...
135 MM
 
13.11.14
11:23
(130) Событийное управление. По какой кнопке щёлкнешь та и запустится, но пока работает обработчик одной из них, остальные будут висеть.
В лучшем случае, они будут переключаться, пока задача запущенная будет чего, то ждать, например, ввода пользователя.
136 MM
 
13.11.14
11:26
(134) Вообще-то, достижением можно считать, что подключение к файловой базе может само запускать фоновые сеанс(ы ?), раньше такое было только на сервере 1С. А вот фоновые задания, вероятно, работают в отдельных потоках. Клиент становится многопоточным.
137 arsik
 
гуру
13.11.14
11:27
(135) (134) Нет не пробовал, я даже с управляемымми формами не работал :)
138 К_Дач
 
13.11.14
12:21
(125) а кстати, вариант! передавать из формы, и форму в родительском сеансе не закрывать, адрес временного хранилища запихнуть в регистр сведений
139 tridog
 
13.11.14
12:28
(136) Фоновые задания, безусловно, выполняются в отдельном потоке. Но тут важно, что они выполняются в отдельном сеансе (также, как и в серверной версии) - т.е. это не многопоточное программирование в традиционном виде - нельзя из нескольких потоков читать и писать одну переменную и т.д.
Единственным разделяемым ресурсом между такими "потоками" является база данных и некоторые механизмы кластера (эмулируемые в файловой версии). С объектами синхронизации все еще грустнее.

Исходя из этого, утверждать, что в 8.3 сделали многопоточность - бред сивой кобылы.
140 tridog
 
13.11.14
12:29
(125) (138) Тоже очень плохой вариант. Вызовет многократное копирование этой таблицы в оперативной памяти.

Если даже при передаче ТЗ параметром в фоновое задание памяти уже не хватает - в этом случае не хватит тем более.
141 К_Дач
 
13.11.14
12:59
(140) эммм... да, точняк...
142 Гёдза
 
13.11.14
13:02
а почему не регистр???
143 arsik
 
гуру
13.11.14
13:10
(140) во временное хранилище нужно запихнуть запрос с временной таблицей и менеджер временных таблиц.
144 DrZombi
 
гуру
13.11.14
13:20
(138) К чему такие сложности :(
Все куда проще, вот кусок кода, как распределить, что либо по процессам.
Вместо города можно использовать свою таблицу значений :)


Функция ПодготовитьФоновыеЗадания(ГородаТЗ) Экспорт
    
    //ТЗ_ФоновыеЗадания  Ключ, Выполняется, Выполнено, Адрес, НомерФЗ
    ТЗ_ФоновыеЗадания = Новый ТаблицаЗначений;
    ТЗ_ФоновыеЗадания.Колонки.Добавить("Ключ",Новый ОписаниеТипов("Строка"));
    ТЗ_ФоновыеЗадания.Колонки.Добавить("Выполняется",Новый ОписаниеТипов("Булево"));
    ТЗ_ФоновыеЗадания.Колонки.Добавить("Выполнено",Новый ОписаниеТипов("Булево"));
    ТЗ_ФоновыеЗадания.Колонки.Добавить("Адрес",Новый ОписаниеТипов("Строка"));
    ТЗ_ФоновыеЗадания.Колонки.Добавить("НомерФЗ",Новый ОписаниеТипов("Число"));
    
    Если ГородаТЗ.Количество() = 0 Тогда
        Возврат ТЗ_ФоновыеЗадания;
    КонецЕсли;
    
    //Город, КоличЭН, НомерФЗ
    Если ГородаТЗ.Количество() <= 10 Тогда
        НомерФЗ = 0;
        Для Каждого СтрокаГород Из ГородаТЗ Цикл
            НомерФЗ = НомерФЗ + 1;
            
            УникИД = Новый УникальныйИдентификатор;
            
            СтрокаФЗ = ТЗ_ФоновыеЗадания.Добавить();
            СтрокаФЗ.Ключ  = Строка(УникИД);
            СтрокаФЗ.Адрес = ПоместитьВоВременноеХранилище(Истина,УникИД);
            СтрокаФЗ.НомерФЗ = НомерФЗ;
            
            СтрокаГород.НомерФЗ = НомерФЗ;
        КонецЦикла;
        
    Иначе
        //Больше 10-ти... придется до укомплектовывать!!!...
        НомерФЗ = 0;
        
        пЗадач         = 10;
        ВсегоГородов = ГородаТЗ.Количество();
        
        ОтборСтрок = Новый Структура("НомерФЗ",0);
        
        Пока пЗадач > 0 Цикл
            НомерФЗ = НомерФЗ + 1;
            
            КолГорЦел = Цел(ВсегоГородов/пЗадач);
            
            Если КолГорЦел <> ВсегоГородов/пЗадач Тогда
                КолГорЦел = КолГорЦел + 1;
            КонецЕсли;
            ВсегоГородов = ВсегоГородов - КолГорЦел;
            
            //Запишем
            УникИД = Новый УникальныйИдентификатор;
            
            СтрокаФЗ = ТЗ_ФоновыеЗадания.Добавить();
            СтрокаФЗ.Ключ  = Строка(УникИД);
            СтрокаФЗ.Адрес = ПоместитьВоВременноеХранилище(Истина,УникИД);
            СтрокаФЗ.НомерФЗ = НомерФЗ;
            
            МассивСтрокГородов = ГородаТЗ.НайтиСтроки(ОтборСтрок);
            Если МассивСтрокГородов.Количество() = 0 Тогда
                Прервать;
            КонецЕсли;
            
            Для Каждого СтрокаГород Из МассивСтрокГородов Цикл
                СтрокаГород.НомерФЗ = НомерФЗ;
                
                КолГорЦел = КолГорЦел - 1;
                Если КолГорЦел <= 0 Тогда
                    Прервать;
                КонецЕсли;
            КонецЦикла;
            
            пЗадач = пЗадач - 1;
        КонецЦикла;
    КонецЕсли;
    
    Возврат ТЗ_ФоновыеЗадания;
КонецФункции


&НаСервере
Процедура ЗапуститьФоновыеЗадания()
    
    ГородаТЗ          = рГородаТЗ.Выгрузить();
    ТЗ_ФоновыеЗадания = рФоновыеЗадания.Выгрузить();
    
    ОтборГор = Новый Структура("НомерФЗ",0);
    
    Для Каждого СтрокаФЗ Из ТЗ_ФоновыеЗадания Цикл
        ОтборГор.НомерФЗ = СтрокаФЗ.НомерФЗ;
        МассивСтрокГор = ГородаТЗ.НайтиСтроки(ОтборГор);
        ТЗ_Копия = ГородаТЗ.Скопировать(МассивСтрокГор,"Город");
        МассивГородов = ТЗ_Копия.ВыгрузитьКолонку("Город");
        
        Ключ = СтрокаФЗ.Ключ;
        
        Переменная         = Новый Структура("Город, Ключ, Адрес, ПериодНач,ПериодКон",МассивГородов,Ключ,СтрокаФЗ.Адрес, Объект.ПериодНач, Объект.ПериодКон);
        
        МассивПараметров = Новый Массив;
        МассивПараметров.Добавить(ПолучитьТекстКода());
        МассивПараметров.Добавить(Переменная);
        
        РезСозданияФЗ = ФоновыеЗадания.Выполнить("ОбщегоНазначения.ВыполнитьКод",МассивПараметров, Ключ, "Отчет по синхронизации № "+Строка(СтрокаФЗ.НомерФЗ));
        
        СтрокаФЗ.Выполняется = Истина;
        СтрокаФЗ.УникИД         = РезСозданияФЗ.УникальныйИдентификатор;
    КонецЦикла;
    
    рФоновыеЗадания.Загрузить(ТЗ_ФоновыеЗадания);
    
КонецПроцедуры


&НаСервере
Функция ПолучитьТекстКода()
    
    ТекстКода = "
    | ОбрСинх = Обработки.ТвояОбработкаВКонфигураторе.Создать();
    | ОбрСинх.ПериодНач = Переменная.ПериодНач;
    | ОбрСинх.ПериодКон = Переменная.ПериодКон;
    | ТЗ_Результ = ОбрСинх.ПолучитьДанныеПоЗапросу(Переменная.Город);
    | ПоместитьВоВременноеХранилище(ТЗ_Результ,Переменная.Адрес);
    |";
    
    Возврат ТекстКода;
КонецФункции


Функция ПолучитьДанныеПоЗапросу(Город) Экспорт
//Тут твоё, код который делается в зависимости по отбору "Город" (у тебя будет свой вариант, или варианты)

//ТЗ_Результ - результирующая таблица значений

Возврат ТЗ_Результ;
КонецФуенкции


//Для того, что бы получить результат по фоновым заданиям
//Нужно организовать работу Обработчика заданий и
//опрашивать, завершилась ли работа задания...
//Или сделать это в цикле... но я бы не стал грузить процессор лишней работой
&НаСервере
Функция ПолучитьСтатусПоФоновымЗаданиям(ЗадачаЗавершена)
    
    ГородаТЗ          = рГородаТЗ.Выгрузить();
    ТЗ_ФоновыеЗадания = рФоновыеЗадания.Выгрузить();
    
    ОбновитьТаблФЗ = Ложь;
    
    ОтборСтр = Новый Структура("НомерФЗ",0);
    
    Для Каждого СтрокаФЗ Из ТЗ_ФоновыеЗадания Цикл
        Если СтрокаФЗ.Выполнено = Истина Тогда
            ОтборСтр.НомерФЗ = СтрокаФЗ.НомерФЗ;
            МассивСтрокГор = ГородаТЗ.НайтиСтроки(ОтборСтр);
            Если МассивСтрокГор.Количество() <> 0 Тогда
                КопТЗ = ГородаТЗ.Скопировать(МассивСтрокГор,"КоличЭН");
                ВсегоВыполненоЭН = ВсегоВыполненоЭН + КопТЗ.Итог("КоличЭН");
                КопТЗ.Очистить();
                КопТЗ.Колонки.Очистить();
                КопТЗ = Неопределено;
            КонецЕсли;
        КонецЕсли;
        
        Если СтрокаФЗ.Выполняется = Ложь Тогда
            Продолжить;
        КонецЕсли;
        
        РезСозданияФЗ = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(СтрокаФЗ.УникИД);
        Если РезСозданияФЗ <> Неопределено Тогда
            Если РезСозданияФЗ.Состояние = СостояниеФоновогоЗадания.Активно Тогда
            Иначе
                СтрокаФЗ.Выполняется = Ложь;
                Если РезСозданияФЗ.Состояние = СостояниеФоновогоЗадания.Завершено Тогда
                    СтрокаФЗ.Выполнено = Истина;
                КонецЕсли;
                
                ОбновитьТаблФЗ = Истина;
            КонецЕсли;
        Иначе
            СтрокаФЗ.Выполняется = Ложь;
            СтрокаФЗ.Выполнено = Истина;
            
            ОбновитьТаблФЗ = Истина;
        КонецЕсли;
    КонецЦикла;
    
    Если ОбновитьТаблФЗ = Истина Тогда
        рФоновыеЗадания.Загрузить(ТЗ_ФоновыеЗадания);
    КонецЕсли;
    

КонецФункции


//Где то еще по коду
&НаКлиенте
Процедура ОбновитьИнформациюФоновогоЗадания() Экспорт
    
    ЗадачаЗавершена = Ложь;
    
    рСтрокаСостояния = ""+ПолучитьСтатусПоФоновымЗаданиям(ЗадачаЗавершена);
    
    Если ЗадачаЗавершена = Истина Тогда
        //Остановить выполнения
        ЭтаФорма.ОтключитьОбработчикОжидания("ОбновитьИнформациюФоновогоЗадания");
        рЗапущеныФоновыеЗадания = Ложь;
        
        //Получить данные по фоновым заданиям и Вывести отчет....
        СформироватьОтчетФЗ();
        
    КонецЕсли;
    
КонецПроцедуры

//По завершению всех фоновых заданий...
ТЗ_Результ = ПолучитьДанныеПоФЗ(ТЗ_ФоновыеЗадания);

Функция ПолучитьДанныеПоФЗ(ТЗ_ФоновыеЗадания)
    
    ТЗ_Результ = Новый ТаблицаЗначений;
        //Структура колонок у тебя будет своя :)
    
    Для Каждого СтрокаФЗ Из ТЗ_ФоновыеЗадания Цикл
        Адрес = СтрокаФЗ.Адрес;
        Если ЭтоАдресВременногоХранилища(Адрес) Тогда
            ТЗ = ПолучитьИзВременногоХранилища(Адрес);
            Если ТЗ = Неопределено или ТипЗнч(ТЗ) <> Тип("ТаблицаЗначений") Тогда
                СообщПольз = Новый СообщениеПользователю;
                СообщПольз.Текст = "Ошибка при формировании отчета № "+Строка(СтрокаФЗ.НомерФЗ);
                Продолжить;
            КонецЕсли;
            
            Для Каждого СтрокаТЗ Из ТЗ Цикл
                СтрокаРез = ТЗ_Результ.Добавить();
                ЗаполнитьЗначенияСвойств(СтрокаРез, СтрокаТЗ);
            КонецЦикла;
        КонецЕсли;
    КонецЦикла;
    
    Возврат ТЗ_Результ;
КонецФункции
145 DrZombi
 
гуру
13.11.14
13:24
+(144)  Еще в общем модуле "ОбщегоНазначения" пишешь
У тебя будет свой модуль, главное, что бы он выполнялся только на сервере :)

Процедура ВыполнитьКод(ТекстКода, Переменная) Экспорт
    Выполнить(ТекстКода);
КонецПроцедуры
146 tridog
 
13.11.14
13:25
(143) Менеджер временных таблиц нельзя помещать во временное хранилище.
147 DrZombi
 
гуру
13.11.14
13:26
(143) Это вообще ненужно делать :)
148 H A D G E H O G s
 
13.11.14
13:27
(146) Это печально.
149 К_Дач
 
13.11.14
13:44
ГородаТЗ          = рГородаТЗ.Выгрузить()

эта строка не будет в каждом фоне создавать ТЗ и дублировать ее в ОЗУ, о чем справделиво сказал (140)
150 К_Дач
 
13.11.14
13:44
будет создавать
151 zsergey
 
13.11.14
13:49
(55) <<Мне то они не нужны, типовой расчет себестоимости в упп 1.3
152 zsergey
 
13.11.14
13:49
+ в каком именно регистре столько записей?
153 tridog
 
13.11.14
13:51
(148) Если правильно понимаю - это плата за кластер
154 H A D G E H O G s
 
13.11.14
13:51
Копирование ТЗ в памяти - это глупости и мелочи, это не о чем.
А вот передача ТЗ через временное хранилище вызовет ее сериализацию (самое забавное, что 1С скорее всего делает тупо инкремент результирующей строки, вызывая realloc) и передачу строки в соседний процесс.

И это логично и понятно.
155 H A D G E H O G s
 
13.11.14
13:52
(153) Да. Но, балин, че бы не разрулить эту ситуевину через глобальные временные.
156 H A D G E H O G s
 
13.11.14
13:53
(153) Или хоть бы теже локальные, доступные пока сеанс 1С не ушел на другой сеанс SQL.
157 tridog
 
13.11.14
13:57
(154) Фоновое задание может запустить на другом rphost'е. А еще - перед вызовом все параметры фонового задания передаются в rmngr и удерживаютя в нем - фиг знает сколько времени после того, как задание выполнится, можно прочитать его параметры через ФоновыеЗадания.Получить() - именно за счет того, что параметры удареживаются в rmngr.

Поэтому все, что передается параметром фонового задания не может быть просто скопировано в памяти - только сериализация, только хардкор)
158 H A D G E H O G s
 
13.11.14
13:58
(157) У меня там приписка:

И это логично и понятно.
159 cons74
 
13.11.14
14:03
тз хз фз тч xdto...
160 tridog
 
13.11.14
14:35
(158) упс, не заметил)
161 MM
 
13.11.14
14:39
(154) На другом компьютере с другой битностью, и даже на другую ОС.
(155) А они точно есть под Постгре и ДБ2? Решение-то задумано как универсальное.
162 H A D G E H O G s
 
13.11.14
14:41
(161) "На другом компьютере с другой битностью, и даже на другую ОС. "

Не понял вопроса.

(155) "А они точно есть под Постгре и ДБ2? Решение-то задумано как универсальное."

А ХЗ. Даже если так - Постгре и ДБ2 вместе с Линуксом идут лесом. Микрософт - наше фсё!
163 Solemn
 
13.11.14
14:48
(36)>"Пусть фоны читают ТЗ и ждут, пока все флаги в служебном регистре сведений не установятся в "Можно писать""

Не догоняю как организовать 1С-ным кодом чтобы фоны "ждали"

(152) УчетЗатратРегл например
164 MM
 
13.11.14
14:50
(162) То что сериализация решает проблему с длинной указателей (связывающих структуры данных, из которых состоит объект), порядком байт и способом хранения в развёрнутом виде у получателя этих передаваемых данных.
1С стремилось к кроссплатформенности. А плата как обычно эффективность.
165 DrZombi
 
гуру
13.11.14
14:50
(149) Приведенный код состоит из разных частей :)
Один код, где объявлен "&НаКлиене НаСервере". Выполняется на форме ;)
Где этого кода нет, выполняется в модуле обработки.
166 DrZombi
 
гуру
13.11.14
14:52
(150) Не будет, если напишешь правильно, то нечего не будет лишнего сдаваться. :)
И что значит создавать?
Тебе нудно просто получить ТЗ, вместо объекта на форме. :)
167 H A D G E H O G s
 
13.11.14
14:52
(164) Нет. Сериализация решает проблему прежде всего с отсутствием объекта в памяти, на который ссылается ячейка таблицы значения. И уже потом длины указателей.
168 DrZombi
 
гуру
13.11.14
14:52
+(166) Не забывай, фоновое задание, это как бы отдельный пользователь.
169 MM
 
13.11.14
14:59
(167) Т.е. если скопировать память объекта из 32х битного процесса в 64х битный, в которой будут находится указатели или целые числа, длина которых зависит от архитектуры процессора, то проблем не будет? Там же всё сползёт.
Если сериализация почему-то табу, то указатели можно попробовать заменить на дескрипторы, без привязки к адресу памяти, тогда данные можно будет копировать memcpy, но это уже в порядке бреда.
170 H A D G E H O G s
 
13.11.14
15:08
(169) Длина целых чисел не зависит от процессора.
А вот размер указателя - да.
И в этом случае все равно можно извратиться - резервируя 4 лишних старших байта возле указателя возле 32-х разрядного процесса. Но все равно, для длинных строк придется выделять динамическую память и заполнять указатели новыми значениями. Но это все равно на порядки быстрее, чем сериализация.
171 H A D G E H O G s
 
13.11.14
15:09
(170) Но это не решает проблему непримитивных типов, которые могут содержаться в ячейке таблицы.
172 MM
 
13.11.14
15:18
(170) Размер int зависит от компилятора. Никто не мешает ему сделать 64-битный int на 32-хразрядной машине. И наоборот. Многие компиляторы для 64-битных платформ все равно оставляют int 32-хбитным.
http://rsdn.ru/forum/cpp/2334752.flat
Или авторитетнее: http://ru.cppreference.com/w/cpp/language/types
(171) Непримитивный тип - это объект, значит в ячейке хранится ссылка на него. А как эта ссылка технически реализована это уже детали, может как указатель на память, а может, как гуид объекта, который был ему задан в процессе сериализации.
173 H A D G E H O G s
 
13.11.14
15:24
(172)
"Размер int зависит от компилятора. Никто не мешает ему сделать 64-битный int на 32-хразрядной машине. И наоборот. Многие компиляторы для 64-битных платформ все равно оставляют int 32-хбитным. "

Итить колотить, да какая разница. Речь о данных, а не о коде.

Это я к тому, что системе пофиг, какие там данные, ей важно чтобы указатели/дескрипторы/callback параметры были нужной размерности.
174 MM
 
13.11.14
15:34
Так и я о данных, rphost 32х не обязан создавать точные аналоги структур ДАННЫХ используемые под 64х, тут ведь глядишь и 128-битные процессоры выпустят. )
И не забываем про Линукс. Не думаю, что указатели/дескрипторы/callback имеет смысл переносить между компьютерами.
А ещё многие просят платформу под Мак, там, кажется, даже порядок байт в числах может быть другим. wiki:Порядок_байт
175 К_Дач
 
13.11.14
15:44
(168) 1 сеанс получает ТЗ, передает на сервер 1С и кладет во временное хранилище. Как тут уже выше писали, это сериализация в строку в чистом виде, передача строки из 12 млн записей - не думаю, что это быстро, это раз... уж если xml-ка с 5 млн записей регистра весила у меня порядка 10 Гб, то тут.....

все последующие сеансы (фоны) должны работать с ТЗ, а не со строкой из ВХ, следовательно, они должны оттуда ее достать, твоя строчка Тз = Фон.Выгрузить() как раз это и делает. Тз грузится в ОЗУ, а значит каждый фон сожрет все ОЗУ на сервере 1С.

Или я что-то в твоем коде не увидел особенного?
176 H A D G E H O G s
 
13.11.14
15:48
(175) Передача строки из 12 млн записей - это быстро.
Медленно - это формирование строки, особенно если инкрементом.
177 H A D G E H O G s
 
13.11.14
15:50
Кстати, менеджер rmmngr мог бы работать с rphost-ами через именованные каналы, но я не заметил этого. Надеюсь, он работает через shared memory.
178 H A D G E H O G s
 
13.11.14
15:52
Эххх, поработать бы мне разработчиком платформы, я бы там такого наворотил! А потом бы вы все плакали горючими слезами.
179 К_Дач
 
13.11.14
15:53
(177) имхается, что shared memory все же, недаром советуют ее включать в случае разворачивания элементов кластера на 1 физическом сервере
180 Serginio1
 
13.11.14
15:55
(177) Для этого нужен свой менеджер памяти как в Delphi
http://rsdn.ru/article/Delphi/memmanager.xml

или Exchange Heap


http://rsdn.ru/article/singularity/singularity.xml#EFKAC
181 H A D G E H O G s
 
13.11.14
15:56
(179) Это между сервером 1С и SQL.
182 DrZombi
 
гуру
13.11.14
15:56
(177) Теоретически он не должен работать вообще :)
183 DrZombi
 
гуру
13.11.14
15:56
+(182) Между заданиями
184 H A D G E H O G s
 
13.11.14
15:56
(180) Это для какого случая?
185 H A D G E H O G s
 
13.11.14
15:58
(180) Именнованные каналы шикарны. Там уже все реализовано (передача данных, синхронизация) на уровне ОС, там даже данные по сети можно передавать.
186 MM
 
13.11.14
16:08
(185) И опять я со своим дёгтем, это должно как-то работать в Линуксе, так что каналы не подходят. А общая память пойдёт только в пределах одной машины, а значит будет писаться когда отладят межмашинное взаимодействие.
Я Линукс не знаю, но 1С почему-то радеет за кроссплатформенность.
Кстати, именованные каналы у меня зависали чаще, чем сокеты на UDP.
187 H A D G E H O G s
 
13.11.14
16:13
(186) А я счаст говорю о уровне
менеджер кластера- процессы сервера 1С.
188 Serginio1
 
13.11.14
16:13
(185) Ты плохо прочитал про Exchange Heap  это использование общей памяти между доменами, а не просто передача.

Передача по каналам например тебе нужно все равно сериализовывать, ибо в 1С для объектов идет подсчет ссылок, свой менеджер памяти итд.
Можно так передавать только массив структур Валуе типов.
Проблема все этой темы это глобальные временные таблицы которых нет в 1С.
189 H A D G E H O G s
 
13.11.14
16:16
(188) Да понятно, что нужно сериализовывать.
190 Гёдза
 
13.11.14
16:19
(188) может в 8.4 будут )))
191 Гёдза
 
13.11.14
16:19
я так и не понял почему от регистра отказались?
192 H A D G E H O G s
 
13.11.14
16:23
(191) Там всякие гейтсо-мерские индексы будут обновляться.
193 tridog
 
13.11.14
16:24
(178) И что же мешает?)
194 Serginio1
 
13.11.14
16:25
(190) Можно конечно внешние источники использовать, но как там с типизацией, как впрочем и для глобальных таблиц?
(191) Наверное потому, что в отличие от временных таблиц у 1С нет массовой записи в регистр из тз.
Самому приходилось через булки и Merge обновлять регистры напрямую.
195 MM
 
13.11.14
16:27
(187) Так рабочие процессы могут работать на серверах в сети, для масштабируемости и отказоустойчивости, отделённых от менеджеров кластеров. Даже менеджеры кластера можно сделать различными и разнести по разным компьютерам, раздав им свои сервисы, вроде сервисов нумерации, работы с внешними источниками, блокировок разных видов и т.д.
А ещё там есть передача сеансовых данных от главного менеджера к резервному, она тоже требует сериализации.
196 Serginio1
 
13.11.14
16:29
194 Вернее он есть, но такой медленный. Там мало того, что по 1 записи, попутно удаляя старые записи. Нет Merge.
А учитывая индексы там можно просто вешаться на 12 миллионах. По 3 часа помню на 4 миллионах было.
197 К_Дач
 
13.11.14
16:59
(194) а как ты сам писал регистратора или ссылочные типы?
198 Solemn
 
13.11.14
17:06
(133) Только так и проводим
199 Serginio1
 
13.11.14
17:27
(197) Я писал в регистр сведений.
Типа такого
Стр="
     |BEGIN TRAN;
     |If OBJECT_ID('TempDB.dbo.#TempPrice') is not NULL DROP TABLE  #TempPrice;
     |Declare @ТекущаяДата as datetime= GetDate()
     |Declare @Прайс as binary(16) = "+ПолучитьGUIDПоУникальномуИдентификатору(ТипЦен.УникальныйИдентификатор())+"
     |Declare @Импорт as Binary(1) ="+ ?(ТипЦен.Импорт,"0x01","0x00")+";
     |Declare @x as int= (Select Count(*) From dbo."+СтрРегПрайсов.ИмяТаблицыХранения+ " WITH (UPDLOCK)
     | where "+РегПрайсовПоля.ТипЦен+"=@Прайс);";

     Если МейкУстановлен Тогда
         Стр=Стр+"
         |Declare @Мейк as binary(16) = "+ПолучитьGUIDПоУникальномуИдентификатору(УстановленМейк.УникальныйИдентификатор())+";";
     КонецЕсли;
     СтрАртикул=ТзЗагрузКолонок[0];
     СтрСелект="SELECT distinct "+СтрАртикул.СтрокаПоля+",@Прайс as Прайс,";
     Если МейкУстановлен Тогда
         СтрСелект=СтрСелект+"@Мейк as Мейк"
     Иначе
         СтрСелект=СтрСелект+"ТаблицаМейков._IDRRef as Мейк";
     КонецЕсли;
    
     Для сч=4-1 По ТзЗагрузКолонок.Количество()-1 Цикл
         Строка=ТзЗагрузКолонок[сч];
         Если Строка.Использование Тогда
             СтрСелект=СтрСелект+","+Строка.СтрокаПоля
         КонецЕсли;
     КонецЦикла;
    
     Стр=Стр+"
     |"+СтрСелект+"
     |INTO #TempPrice
     |FROM OPENROWSET( BULK N'"+ФайлСПрайсом+"',
     |FORMATFILE = N'"+ИмяФайлаФрмата+"',";
200 Serginio1
 
13.11.14
17:29
201 К_Дач
 
13.11.14
17:33
(200) я имел ввиду как ты Справочник.Номенклатура например преобразовывал в binary(16), там же в поле таблицы, соответствующей ссылочному измерению этот тип
202 Serginio1
 
13.11.14
17:43
(201)
Функция ПолучитьGUIDПоУникальномуИдентификатору(UUID1)
    UUID=ВРЕГ(UUID1);
    ч1 = Сред(UUID,20,4);
    ч2 = Сред(UUID,25,12);
    ч3 = Сред(UUID,15,4);
    ч4 = Сред(UUID,10,4);
    ч5 = Сред(UUID,1,8);
    Возврат "0x" + ч1 + ч2 + ч3 + ч4 + ч5;
КонецФункции
203 Целина
 
13.11.14
17:43
(0)у тебя ответ в вопросе
алгоритм допускает многопоточную обработку
(кстати любой)
нужно или до создания таблицы его изменить так чтобы было много мелких таблиц
или передавать частями
а лучше выпилить таблицы значений и вычислять всё в скулях
204 Целина
 
13.11.14
17:45
проблему с недокументированными ссылочными полями можно решить. сделать записей сколько нужно где нужно платформой а потом их проапдейтить скулем.
205 Reaper_1c
 
13.11.14
17:51
(198) Какой из процессов ты надумал распустить на потоки? А то я слабо верю, чтобы матрица системы одного узла корректировки стоимости набрала 12 миллионов строк...
206 Reaper_1c
 
13.11.14
17:58
В (205) фигню ляпнул - имелся в виду не узел а выделенный граф из всего расчета. Или ты кораблестроение автоматизируешь?
207 Solemn
 
13.11.14
18:04
(206) 12 млн это количество записей в регистре УчетЗатратРегл перед сверткой
208 Целина
 
14.11.14
10:37
(207)и что их сразу на сервере прочитать нельзя??? )))
209 Serginio1
 
14.11.14
10:42
(0) Сериализуй в файл
ЗаписьXML = Новый ЗаписьXML;
    ЗаписьXML.ОткрытьФайл(ИмяФайла);
   СериализаторXDTO.ЗаписатьXML(ЗаписьXML, Источник);
   ЗаписьXML.Закрыть();

А в параметрах передавай ИмяФайла и загружай сериализатором через чтение файла
210 Solemn
 
14.11.14
11:08
(208) Можно, но только 1 раз, потом они будут изменены, это уже обсуждалось выше
211 Solemn
 
14.11.14
11:30
+(210) в одном фоне можно прочитать
212 Serginio1
 
14.11.14
11:44
(211) Можешь и в разных. Скорее всего ЧтениеXML открывается только на чтение.
213 tridog
 
14.11.14
11:51
(209) Это будет работать до появления второго сервера в кластере
214 Serginio1
 
14.11.14
11:58
(213) Всмысле? Что при этом с файлом случится?
215 tridog
 
14.11.14
12:10
(214) Он останется на том сервере, на котором был создан.
А фоновое задание запустится на другом сервере. На котором этого файла отродясь не было.
216 Serginio1
 
14.11.14
12:21
(215) Угу то есть если ты файл записал в расшаренную то ты этот файл не увидишь? Есть еще FTP, НTTP ресурсы
217 tridog
 
14.11.14
12:54
(216) Из расшаренной - увидишь, если она будет доступна с обоих серверов. Только это:
1. Снижает надежность - появляется еще одна точка отказа
2. Усложняет развертывание - представь, что в серверной был пожар и надо срочно все поднять из бекапов - про расшаренную папку никто и не вспомнит
3. Не по феншую
218 Serginio1
 
14.11.14
13:27
(217) Главное, что бы работало, а все остальное это уже поиски фэншуя. Так или иначе, большинство файлов держат не в базе а рядом с ней. Например
Хранилище FILESTREAM объединяет компонент SQL Server Database Engine с файловой системой NTFS, размещая данные больших двоичных объектов (BLOB) типа varbinary(max) в файловой системе в виде файлов. С помощью инструкций Transact-SQL можно вставлять, обновлять, запрашивать, выполнять поиск и выполнять резервное копирование данных FILESTREAM. Интерфейсы файловой системы Win32 предоставляют потоковый доступ к этим данным.

Для кэширования данных файлов в хранилище FILESTREAM используется системный кэш NT. Это позволяет снизить возможное влияние данных FILESTREAM на производительность компонента Database Engine. Буферный пул SQL Server не используется, поэтому данная память доступна для обработки запросов.


http://technet.microsoft.com/ru-ru/library/bb933993(v=sql.105).aspx
219 Serginio1
 
14.11.14
13:38
220 Целина
 
14.11.14
14:10
(210)
не читал всё внимательно
но
если ты держишь их в памяти в тз только чтобы иметь исходник сделай регистр2 и храни там
221 Solemn
 
14.11.14
15:12
(220) большая потеря времени на запись в регистр2, теряется смысл многопоточности, время работы в итоге не уменьшается, а может еще и увеличится
222 arsik
 
гуру
14.11.14
15:15
самое нормально мне кажется напрямую с SQL работать. Вытащить там все данные во временную таблицу внутри SQL и уже фоновыми оттуда забирать то что нужно.
223 H A D G E H O G s
 
14.11.14
15:17
Можно вопрос - а что мешает прочитать по частям этот УчетЗатрат в несколько потоков?
224 H A D G E H O G s
 
14.11.14
15:17
(223) Если там алгоритм обработки можно распаралелить.
225 Гёдза
 
14.11.14
15:19
(221) у тебя небось регистр со всеми полями - измерениями?
226 Лефмихалыч
 
14.11.14
15:19
(223) гы, я уже спрашивал на первой странице
227 arsik
 
гуру
14.11.14
15:21
(223) Я так понимаю. он динамично меняется. Надо одномоментно прочитать, и потом уже разбиратся с тем что прочитали. Иначе из этих частей не соберется исходный массив.
228 H A D G E H O G s
 
14.11.14
15:33
(227) Из родительского процесса наложить разделяемую блокировку.

Фоновые процессы прочтут регистр накопления и отчитаются в Регистр сведений.

Родительский процесс ждет отчета от всех фоновых и снимает блокировку.
229 Целина
 
14.11.14
15:51
(221)пиши скулем какие проблемы?
230 Целина
 
14.11.14
15:54
(223)(224)для этого нужен мозг
(228)сабж предполагает волшебную галочку типа птичка типа чекбокс в настройках сервера
231 H A D G E H O G s
 
14.11.14
16:01
(230) "типа птичка типа чекбокс в настройках сервера"

Это какую?
232 tridog
 
14.11.14
16:05
(228) Вот мы и дошли до изобретения RPC) Как предлагаешь из фоновых передавать инйормацию в родительский?)
233 H A D G E H O G s
 
14.11.14
16:08
(232)
Написал же, регистр сведений.
234 Целина
 
14.11.14
16:12
судя по вопросам автор сабжа со всем отделом всё равно не справится )))
235 H A D G E H O G s
 
14.11.14
16:21
(234) Ты справишься еще меньше.
236 tridog
 
14.11.14
16:26
(233) Я тоже лучше ничего не придумал. RPC через базу данных. Тоска, пичаль.
237 Serginio1
 
14.11.14
16:33
(236) Лучше это прямой доступ к БД и использование всей мощи SQL
238 Целина
 
14.11.14
16:35
(235)тогда поставь сервак 64 и подкачку 100 и жди )))
авось!
239 tridog
 
14.11.14
16:36
(237) SQL-сервер не есть "серебрянная пуля"
Если задача реально обеспечить параллельность - то чем он тебе поможет?
240 Serginio1
 
14.11.14
16:40
(239) А  транзакции и блокировки для кого придуманы?
241 Serginio1
 
14.11.14
16:42
Вернее уровни изоляции транзакции
242 Целина
 
14.11.14
16:50
(239)ну если распараллелить расчеты лень то можно дать скулям посчитать.
мы же не знаем нафига ему эта таблица и насколько он знает скуль.
выигрыш там будет несколько порядков. естественно на апдейтах. ибо не исключено что с помощью курсоров он и там сервак повесит.
243 Solemn
 
14.11.14
17:00
(228) Расчет происходит ВНЕ ТРАНЗАКЦИИ, блокировки не сработают, плюс таймаут (если бы было в транзакции) никто не отменял
(232) Для получения из фоновых в родительский обычно используется ПоместитьВоВременноеХранилище
(234) Вы предлагаете свою помощь? Справитесь? :)
(240) Расчет ВНЕ ТРАНЗАКЦИИ
(242) :) нет доступа к БД, так что ваш совет не подходит
244 Serginio1
 
14.11.14
17:02
(243) Так десериализацию из файла не пробовал?
245 H A D G E H O G s
 
14.11.14
17:03
(243) Расчет происходит ВНЕ ТРАНЗАКЦИИ.

Как это относиться к тому, что я написал в (228)?
246 H A D G E H O G s
 
14.11.14
17:04
(243) Таймаут реализуй через скрипт.
247 Solemn
 
14.11.14
17:08
(245)управляемые блокировки работают только в транзакции
248 Господин ПЖ
 
14.11.14
17:10
>нет доступа к БД

разверни рядом другой экземпляр скуля, суй в него
249 H A D G E H O G s
 
14.11.14
17:10
(247) Используй
НачатьТранзакцию();
250 Целина
 
14.11.14
17:33
(243)у тебя его нет потому что тебе он не поможет.
тем кто умеет его готовить дают.