Имя: Пароль:
1C
1С v8
Быстрая загрузка данных из базы SQL
0 Lepochkin
 
29.09.14
11:41
Добрый день, всем. Есть такая задачка. Имеется база SQL. К ней я делаю запрос и получаю данные. Далее эти данные помещаю с таблица значений, таблицу значений передаю как параметр в запрос 1совский и дальше с ней работаю. Дак вот табличка с данными стала ну уж очень большой, и уходит порядка получаса для того, что бы прямым перебором ее запихать в таблицу значений. Есть ли как-нибудь другой способ? Внешний источник данных пробовал. Ничего хорошего.
1 КонецЦикла
 
29.09.14
11:43
Временные таблицы? Не, не слышол
2 Ерепень
 
29.09.14
11:43
а напрямую запросить? подозреваю, будет то же, что и с внешним источником
3 Жан Пердежон
 
29.09.14
11:45
(0) большая это сколько?
4 shuhard
 
29.09.14
11:50
(0)[Есть ли как-нибудь другой способ]
засунуть напрямки в табличку 1С на сиквеле
5 ice777
 
29.09.14
11:53
примерно так:

Вставка = "бла-бла первый запрос"

Второй запрос = "......"+ Вставка + "....."
6 ice777
 
29.09.14
11:54
* "вставку" вставь там, куда ТЗ свою сувал.

это по-простому
7 ДенисЧ
 
29.09.14
11:57
хм....
А дайте код создание временной таблицы в скуле, чтобы к ней потом запросом 1с можно было обратиться....

(0) И да, код вытяжки покажи....
8 Lepochkin
 
29.09.14
12:03
(1) Вот как бы из скуля по временную таблицу 1ски сделать. хочу знать
(3) 4 миллиона записей сейчас и прогнозируется рост
(5) Не понял
(7) Тут все наверное стандартно

    Если НЕ RecordSet.EOF() Тогда
        RecordSet.MoveFirst();                
        Пока RecordSet.EOF() = 0 Цикл
            //Состояние("Загрузка данных: "+строка(ИД));
            СтрокаТаблицыЗначений = тз.Добавить();
            Для НомерКолонки = 0 По RecordSet.Fields.Count-1 Цикл
                СтрокаТаблицыЗначений[НомерКолонки] = RecordSet.Fields(RecordSet.Fields.Item(НомерКолонки).Name).Value;
            КонецЦикла;
            RecordSet.MoveNext();  
            ИД = ИД + 1;
        КонецЦикла;
    КонецЕсли;
9 ДенисЧ
 
29.09.14
12:04
(8) измени вот эту строку
RecordSet.Fields(RecordSet.Fields.Item(НомерКолонки).Name).Value;

перед циклом получай все элементы Fields в переменные. Намного быстрее будет.
10 Lepochkin
 
29.09.14
12:15
(9) Не понял как этот должно выглядеть
11 ДенисЧ
 
29.09.14
12:16
имяПеременной0 = RS.Fields(0);
....
ИмяПеременнойN = RS.Fields(0);

пока не RS.EOF Цикл
  Значение0 = имяПеременной0.Value;
....
  rs.MoveNext();
КонецЦикла
12 Lepochkin
 
29.09.14
12:24
Как-то так получилось. Вроде работает

    Для НомерКолонки = 0 По RecordSet.Fields.Count-1 Цикл
        МассивПеременных.Добавить(RecordSet.Fields(НомерКолонки));
    КонецЦикла;
    
    Если НЕ RecordSet.EOF() Тогда
        RecordSet.MoveFirst();                
        Пока RecordSet.EOF() = 0 Цикл
            //Состояние("Загрузка данных: "+строка(ИД));
            СтрокаТаблицыЗначений = тз.Добавить();
            Fields = RecordSet.Fields;
            Для НомерКолонки = 0 По RecordSet.Fields.Count-1 Цикл
                СтрокаТаблицыЗначений[НомерКолонки] = МассивПеременных[НомерКолонки].Value;
            КонецЦикла;
            RecordSet.MoveNext();  
            ИД = ИД + 1;
        КонецЦикла;
    КонецЕсли;

Вечером посмотрим прирост в скорости. Есть еще какие-нибудь варианты ускорения?
13 ДенисЧ
 
29.09.14
12:27
(12) Посмотри на GameWithFire.
Дальше некуда.
14 Зеленый пень
 
29.09.14
12:29
Эти 4 млн. строк в SQL часто обновляются?
Если нет, то я бы тащил только новые и добавлял их в рег.сведений в базе 1С.
Можно делать такое обновление РС в фоновом режиме.
А запрос по РС строить.
15 КонецЦикла
 
29.09.14
12:30
(8) В таблицу SQL с нужным индексом... или в какой-то служебный регистр сведений
16 МихаилМ
 
29.09.14
13:05
читайте про метод ado getrows  http://msdn.microsoft.com/en-us/library/windows/desktop/ms675120(v=vs.85).aspx

если 1с - клиент- серверная , то можно в таблицы бд 1с (РС)записать обработать, затем очистить


можно ускорить чтение данных из скл если написать clr-метод
который превратит выборку в тз спрятанную в хранилище Значений
17 Drac0
 
29.09.14
13:10
(0) Что ты потом с этими данными делаешь в 1С-ом запросе?
18 Широкий
 
29.09.14
13:30
BULK INSERT?
19 Lepochkin
 
29.09.14
13:32
(14) Собственно так и делаю. Получаю данные раз в день, пишу только изменения в регистр, а пользователи уже с регистром работают. Задание стало работать 40 минут. Из них 30 получение данных. Пока еще все терпимо, доводить нетерпимо не хочется.
20 Зеленый пень
 
29.09.14
13:37
(19) Не совсем понятно. Если получение данных сделать заранее - то останется только отчет построить, т.е. 10 сек.
21 Cyberhawk
 
29.09.14
13:40
(19) Храни в приемнике дату актуальности таблицы, а из источника получай только записи, которые актуальнее даты актуальности приемника. Ну, это прокатит, если во внешнем источнике есть timastamp
22 Cyberhawk
 
29.09.14
13:41
(21) * timestamp
23 Lepochkin
 
29.09.14
13:47
с getrows вот такой косяк.

Ошибка при вызове метода контекста (GetRows)
    COMSafeArray = RecordSet.GetRows();
по причине:
Произошла исключительная ситуация (Provider): Недостаточно памяти для завершения операции

на TOP 1000 очень шустро отработала, а вот на полной таблице не взлетело
24 Lepochkin
 
29.09.14
13:48
(20)Отчеты все летают. Данные просто нужны к концу рабочего дня и становится критичное время их закачки в 1ску.
25 YFedor
 
29.09.14
13:50
Не понял зачем здесь вообще ТЗ и запрос в 1С
26 Lepochkin
 
29.09.14
13:52
Хотя бы для того что бы в регистр сведений записать ссылку на номенклатуру, а не ее код, который мне отдает сторонняя база SQL. Плюс дублирующие записи отсечь.
27 Зеленый пень
 
29.09.14
13:53
Можно в SQL повесить триггеры, которые в отдельную таблицу будут добавлять измененные строки, и там всё что угодно можно замутить.
28 rsv
 
29.09.14
14:01
(0) Так что с внешним источником ? Получив оный джойните с чем хотите и не надо никуда перезаливать. Джойнить получится токма в СКД.
29 rsv
 
29.09.14
14:02
4 000 000  это не объем.
30 rsv
 
29.09.14
14:05
в принципе они и были придуманы (источники) для этих целей - для соединения (объеденения ) в единой среде выполнения
31 Lepochkin
 
29.09.14
14:06
При тесте внешнего источника памяти сожрал процесс 2 гига и помер.
32 rsv
 
29.09.14
14:06
Поля поиндексируйте в таблице внешней . может и взлетит.
33 rsv
 
29.09.14
14:07
(31) Ставьте топ 100 при тестах.
34 Lepochkin
 
29.09.14
14:07
Пробовал. Та же история
35 Lepochkin
 
29.09.14
14:08
(33) Первый запуск на TOP 1000 делаю. Если все взлетает, то беру целиком.
36 neckto
 
29.09.14
14:20
(19) На этапе получения данных отсекай уже обработанные, будешь вытаскивать небольшой объем изменений.
37 Lepochkin
 
29.09.14
14:26
(36) Сравнения в цикле делаются медленные чем в запросе. А скулявая база не держит срез последний 1совский.
38 neckto
 
29.09.14
14:31
(37) есть у тебя таблица №1: <ID> <Данные>
Создай в SQL-ной базе таблицу №2: <ID>. Когда получаешь данные, получай из таблицы №1, за исключением данных в таблице №2. Когда в 1С обработаешь записи, пиши в таблицу №2 <ID>. <ID> - одно или комбинация полей.
39 Lepochkin
 
29.09.14
14:49
Со структурой в скульной базе можно конечно попробовать оптимизец навести. Но данных все равно много будет. Так что начальная задачка остается.
40 neckto
 
29.09.14
14:53
(39) Делай обмен чаще.
41 Lepochkin
 
29.09.14
14:57
Чаще плохо. Посчитать не по конечным данным юзеры могут.
42 КонецЦикла
 
29.09.14
15:00
(37) Соединение в запросе, а не сравнение в цикле
Все там моментально будет если применить моск
43 Жан Пердежон
 
29.09.14
15:00
может есть возможность сразу готовые данные получать из SQL?
либо часть данных из 1С помещать в ВТ SQL, а потом уже тянуть запросом результат?
44 neckto
 
29.09.14
15:00
(41) Можно поиграться признаком Активность записи РС.
45 Надо работать
 
29.09.14
15:01
(23) А частями грузить, по миллиону записей допустим?
46 Drac0
 
29.09.14
15:03
(0) Из 4 млн. считаных записей, сколько пишутся в регистр?
47 Йохохо
 
29.09.14
15:15
(46) вангую "500 штук" и проблема добавить в запрос вхере Выражение
48 Lepochkin
 
29.09.14
15:19
(46) 70% примерно. Частями получать тоже можно. Даже реализовано.
49 Drac0
 
29.09.14
15:21
(48) Да ,тогда особо не выиграешь. Тогда, ИМХО, делать запись в технический регистр прямым запросом ,а потом уже с ним работать через 1С.
50 Lepochkin
 
29.09.14
15:24
(49) Вот наверное по такому пути я и пойду.
51 Serginio1
 
29.09.14
15:41
Если табличка регистр сведений, то проще использовать Merge и напрямую писать в регистр сведений
v8: _SimpleKey и его установка
52 Kamas
 
29.09.14
15:44
(51) так что там с клавиатурой то решилось??
53 Serginio1
 
29.09.14
16:13
(52) Без понятия
54 Lepochkin
 
29.09.14
17:23
Переделка из (12) ускорила примерно в 2 раз.
55 МихаилМ
 
29.09.14
18:03
(54)
избавьтесь от

RecordSet.Fields.Count-1
и будет еще быстрей

если будете в getrows()  получать не все данные а порциями
(например по 50000 записей ) будет еще быстрей.
56 Serginio1
 
29.09.14
18:22
Компьютеры — прекрасное средство для решения проблем, которых до их появления не было.