Имя: Пароль:
1C
1С v8
1C + Firebird: долго выполняется выборка данных... можно ли ускорить?
,
0 dave2000
 
30.08.18
17:04
Есть БД Firebird, в таблице заказов сотни тысяц записей, нужно отбирать оттуда данные за период и грузить в 1С. Метод Open() отрабатывает быстро, а вот при первом обращении к EOF() начинается полный тупняк, ждёт где-то полчаса, пока не начнётся перебор записей. Можно ли как-то ускорить работу?



Процедура КнопкаВыполнитьНажатие(Кнопка)
    Conn = Новый COMОбъект ("ADODB.Connection");
    Conn.Open("Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=Northwind");
    
    RS = Новый COMОбъект ("ADODB.RecordSet");
    RS.Open("select * from orders where orders.sdate + orders.sdate >= cast('2018-08-30 15:00:00' as timestamp)", Conn);
    
    Пока НЕ (RS.EOF) Цикл            // <==== при первом обращении к EOF() очень долго думает, дальше перебор идет нормально
        Сообщить(RS.Fields(1).Value());
        RS.MoveNext();
    КонецЦикла;

    RS.Close();
КонецПроцедуры
1 H A D G E H O G s
 
30.08.18
17:06
"orders.sdate + orders.sdate >= cast('2018-08-30 15:00:00' as timestamp)"

Не делай так.
2 Кирпич
 
30.08.18
17:17
(0) ну наверное индексов нету соответствующих и много записей отбираете сразу
3 Кирпич
 
30.08.18
17:19
а вообще, ступай на форум Firebird
4 Кирпич
 
30.08.18
17:26
5 Ненавижу 1С
 
гуру
30.08.18
17:29
что сие условие значит?

orders.sdate + orders.sdate >= cast('2018-08-30 15:00:00' as timestamp)
6 Скиурус
 
30.08.18
17:39
Замени Select * на список нужных тебе полей, исключи из выборки всякие блобы.
7 МихаилМ
 
30.08.18
20:57
+(5)
в продакшене "*" испоьзовать - моветон.
https://forum.infostart.ru/forum9/topic53575/
8 Germes
 
30.08.18
21:34
(0) Плохо знаю восьмерку, но может есть возможность по-другому организвать выборку данных:

1) Делаем 2 запроса: один - на выборку строк, второй - только считающий количество записей с таким же фильтром за период, как первый

2) Цикл по первому рекордсету не через сравнение с EOF, а тупо по счетчику, пока не будет перебрано количество записей, вычисленное вторым запросом.

Таким образом, исключится проверка на EOF, вызывающая большую задержку.
9 dave2000
 
30.08.18
21:53
(1) А как будет правильнее сделать? Там просто в одном поле дата, в другом время хранится

(6) (7) Там в реальности поля стоят, я просто поставил звёздочку, чтобы проще для понимания было.


Пока спасибо всем, натолкнули на мысли, буду пробовать.
10 H A D G E H O G s
 
30.08.18
22:16
(9) (1) А как будет правильнее сделать?

Если это поле orders.sdate индексировано, то твоя формула выключит индекс.
Отбери просто на началодня (или на конец) и отсеки лишнее в постобработке.
11 H A D G E H O G s
 
30.08.18
22:20
Если поле orders.sdate не индексировано - то его надо индексировать.
12 hhhh
 
30.08.18
22:23
(0) Сообщить выкинь, тут на 90% Сообщить время жрет.
13 palsergeich
 
30.08.18
22:27
orders.sdate + orders.sdate>=
Однозначное не использование индекса же.
14 H A D G E H O G s
 
30.08.18
22:29
(13) см (1), (10)
15 H A D G E H O G s
 
30.08.18
22:30
(0) Вот еще можно поиграться с курсорами, но там по дефолту должны стоять оптимальные значения, нуавдруг
http://www.askit.ru/custom/vba_office/m9/09_05_02_recordset_opening.htm
16 H A D G E H O G s
 
30.08.18
22:31
Вот тут с числовыми значениями констант
http://www.askit.ru/custom/progr_admin/m13/13_03_02_ado_recordset_parameters.htm
17 Cyberhawk
 
30.08.18
23:02
А почему в условии одинаковые имена полей, если "в одном поле дата, в другом время хранится"?
18 mcarrowd
 
31.08.18
07:47
можно попробовать не делать отбор по времени (отбирать только по дате, тогда индекс будет работать). При обходе выборки пропускать ненужные записи. Может так получится быстрее.
19 dmpl
 
31.08.18
08:04
(0) Используй PLAN в запросе чтобы явно указать используемый индекс.
20 dmpl
 
31.08.18
08:05
(8) Задержку вызывает исполнение запроса, а не проверка на EOF.
21 Germes
 
31.08.18
09:06
(20) Цитата из (0):

Метод Open([текст запроса]) отрабатывает быстро, а вот _п_р_и_ _п_е_р_в_о_м_ _о_б_р_а_щ_е_н_и_и_ к EOF() ... ждёт где-то полчаса, пока не начнётся перебор записей
22 dmpl
 
31.08.18
09:18
(21) При первом обращении к результату запроса и происходит выполнение запроса. Зачем его выполнять, если еще неизвестно, будет использован результат или нет?
23 dave2000
 
31.08.18
09:37
(17) сори, там sdata + stime, это я автоматом лажанул, когда сюда вписывал

(11) (13) (15) (16) (19) таки да, спасибо за информацию, тоже как раз в этом направлении начал копать )
24 dmpl
 
31.08.18
09:40
(23) Попробуй поставить 2 условия: одно чисто по дате, второе уже по дате + времени и принудительно использовать индекс, где есть поле даты. Тогда высоки шансы, что оптимизатор сначала отберет документы по индексу, а затем уже отбросит те, которые с начала дня не нужны.
25 Сияющий в темноте
 
31.08.18
10:03
Зачем складывать два одинаковых поля????
26 Сияющий в темноте
 
31.08.18
10:04
Наверное,там было stime?
27 Сияющий в темноте
 
31.08.18
10:09
Firebird выполняет запрос при первом обращении к результату.

при подсчете количества он делант полное сканирование,т.к.могут существовать несколько версий одной записи и для низкого уровня,это разные строки.

если долго,то сделайте ему collect garbage,станет быстро.
28 dave2000
 
31.08.18
10:10
Ещё вопрос по поводу метода Open():

  > RS.Open(ТекстЗапроса, Conn);
  > RS.Open(ТекстЗапроса, Conn, 3);

Заметил, что если параметр не задавать (по умолчанию 0), то выборка происходит при первом обращении к EOF(), а если поставить 3, выборка просиходит при самом Open(). На что на самом деле влияет этот параметр при выборке?
29 Cool_Profi
 
31.08.18
10:12
(28) на то, какой курсор будет создаваться

Существует четыре курсор другого типа, определенные в ADO:
Динамический курсор дает возможность просмотра, добавления, изменения и удаления другими пользователями; разрешает все типы перемещения через записей , не зависит от закладки; и позволяет закладки, если поставщик поддерживает их.
Курсор набора ключей добавьте Behaves как динамический курсор, за исключением того, что он не позволяет просматривать записи другие пользователи и предотвращает доступ к записям, которые другие пользователи удаляют. Данные изменения другими пользователями по-прежнему будут отображаться. Здесь всегда поддерживает закладки и поэтому все типы перемещения по записей.
Статический курсор предоставляет статическую копию набора записей можно использовать для поиска данных или создавать отчеты; всегда позволяет закладки, а поэтому все типы перемещения через записей. Дополнения, изменения или удаления других пользователей будет недоступен. Это единственный тип курсора, допускается при открытии на стороне клиента записей объекта.
Однонаправленный курсор позволяет только просмотреть записей. Дополнения, изменения или удаления других пользователей будет недоступен. Это улучшает производительность в ситуациях, когда необходимо сделать только один проход по записей.
30 dmpl
 
31.08.18
10:16
+(24) Еще вариант выбрать 2 таблицы и объединить их. Одна с датой >= 2018-08-31, а вторую - с датой = 2018-03-30 и время >= 15:00:00. В таком случае даже распараллелить исполнение запроса несложно.
31 dave2000
 
31.08.18
10:19
(25) (27) все верно, это я когда сюда писал ошибся (23)

(29) т.е. 0 для простой выборки и дного прохода записей будет оптимально?
32 dave2000
 
31.08.18
10:21
(30) как раз этим путем пробую идти: либо так, либо отбирать с точностью до дня, а в постобработке отсекать ненужные записи
33 Z1
 
31.08.18
10:36
(32) Отбирай в sql запросе ТОЛЬКО  по условию дата=день
по времени отсекай записи на клиенте.

Если еще сможешь понять досконально сам почему как в 0 имееет место быть,
то ты уже на другом уровне по sql
Независимо от того, куда вы едете — это в гору и против ветра!