powered by simpleCommunicator - 2.0.55     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Как ускорить этот цикл? (выборка из архивных файлов по условию)
21 сообщений из 21, страница 1 из 1
Как ускорить этот цикл? (выборка из архивных файлов по условию)
    #36543804
А. С.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Привет всем. Есть код, смысл его в том, что есть архивные файлы с оплатой, они находятся в папках для каждого месяца, а месяца разбиты по годам (но это не важно).
дерево такое:
2008
_01\oplata.dbf
_02\oplata.dbf
_03\oplata.dbf
_NN\oplata.dbf
2009
_01\oplata.dbf
_02\oplata.dbf
_03\oplata.dbf
_NN\oplata.dbf
Задача в курсор выбрать из всех таблиц записи по лицевому счету.
Написал цикл выборки, работает отлично, но во многопользовательском режиме тормозит.
Использую SET KEY на каждой таблице, а потом перебором записей вставляю их в курсор. APPEND FROM добавляет намного медленней. SELECT * - тоже не вариант - вообще глохнет надолго.
Можно ли еще ускорить этот процесс, может есть способы это делать быстрее, чем в приведенном коде?

автор
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
CREATE CURSOR cTemp (DATE D, summa N(13,2))
ADIR(dir,'arhiv\*.*',"D") 
FOR n=1 TO ALEN(dir,1)
	IF AT('D',dir(n,5))>0 AND VAL(dir(n,1))>0
		cYear=dir(n,1)
		FOR nn=1 TO 12
			cMon=PADL(ALLTRIM(STR(nn)),2,'0')
			cPath=CURDIR()+'arhiv\'+cYear+'\'+cMon+'\'
			IF DIRECTORY(cPath)
				cFile=cPath+'oplata.dbf'
				IF FILE(cFile)
					SELECT 0
					USE &cFile ALIAS tmp SHARED
					SET ORDER TO tag id_ls
					SET KEY TO nlsz
					SCAN
						SCATTER TO eee
						SELECT cTemp
						APPEND BLANK
						GATHER FROM eee
					ENDSCAN
					USE IN tmp
				ENDIF
			ENDIF
		ENDFOR
	ENDIF
ENDFOR
...
Рейтинг: 0 / 0
Как ускорить этот цикл? (выборка из архивных файлов по условию)
    #36543870
tanglir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А. С.,

Как получивший подобное наследство заявляю: если есть хоть какая-то возможность, спихни все эти файлы оплат в одну табличку на sql-сервер (только добавь поле "дата" :) ), добавь индекс по ЛС, и выбирай с хорошей скоростью и без этих ублюдочных циклов...
...
Рейтинг: 0 / 0
Как ускорить этот цикл? (выборка из архивных файлов по условию)
    #36543892
А. С.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
sql сервер не вариант, спихнуть в одну таблицу хорошая идея, только таблица разрастется. Как вариант можно одну таблицу вести для каждого года.
Я хотел спросить можно ли сделать выборку быстрее при данных обстоятельствах?
...
Рейтинг: 0 / 0
Как ускорить этот цикл? (выборка из архивных файлов по условию)
    #36544160
karly™
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
1. Какая версия фокса? В VFP9 запросы стали работать намного быстрее.

2. Приведи пример запроса, который "глохнет надолго". Наверняка его можно оптимизировать, и добавлять данные не построчно, а "пачкой"

3. Вместо конструкции "Append Blank + Gather From" можно добавлять данные одной командой Insert from memvar

4. Обработка одной большой таблицы будет быстрее, чем нескольких маленьких. Если данные архивные, то нет проблем создать слить все в одну таблицу
...
Рейтинг: 0 / 0
Как ускорить этот цикл? (выборка из архивных файлов по условию)
    #36544236
А. С.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
karly™1. Какая версия фокса? В VFP9 запросы стали работать намного быстрее.
Простите, 9-ка

karly™2. Приведи пример запроса, который "глохнет надолго". Наверняка его можно оптимизировать, и добавлять данные не построчно, а "пачкой"
Если в цикле на каждой таблице делать
SELEST * FROM tmp INTO CURSOR ttt
а после из курсора вставлять APPEND FROM DBF('ttt')

karly™3. Вместо конструкции "Append Blank + Gather From" можно добавлять данные одной командой Insert from memvar
Спасибо, попробую, только думаю что это вряд-ли ускорит процесс. Я понимаю что у меня загвоздка с открытием самих таблиц, потому что быстрее чем SET KEY TO в моем случае вряд-ли что-то будет работать....

karly™4. Обработка одной большой таблицы будет быстрее, чем нескольких маленьких. Если данные архивные, то нет проблем создать слить все в одну таблицу
Просто у меня в программе все выборки и отчеты интерфейсно заточены под такое дерево. Придется много переделывать. Вот я и спрашваю как еще можно сделать именно для данного представления таблиц.
...
Рейтинг: 0 / 0
Как ускорить этот цикл? (выборка из архивных файлов по условию)
    #36544246
karly™
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А. С.Если в цикле на каждой таблице делать
SELEST * FROM tmp INTO CURSOR ttt
а после из курсора вставлять APPEND FROM DBF('ttt')Условия запроса какие пишете? И какие есть индексы у таблиц?
...
Рейтинг: 0 / 0
Как ускорить этот цикл? (выборка из архивных файлов по условию)
    #36544400
А. С.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
nlsz=555
SELEST * FROM tmp WHERE id_ls=nlsz INTO CURSOR ttt

Индексы в таблицах *.CDX по id_ls присутствуют, но не вижу связи между SELECT * и индексами
...
Рейтинг: 0 / 0
Как ускорить этот цикл? (выборка из архивных файлов по условию)
    #36544407
А. С.не вижу связи между SELECT * и индексамиВот это и плохо ибо связь самая прямая. Наличие правильных индексов очень сильно ускоряет select.
...
Рейтинг: 0 / 0
Как ускорить этот цикл? (выборка из архивных файлов по условию)
    #36544449
karly™
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Посмотрел на код внимательнее

1. Вместо макроподстановки USE &cFile ALIAS tmp SHARED лучше использовать именное выражение USE (cFile) ALIAS tmp SHARED

2. Связка
Код: plaintext
1.
2.
3.
SET ORDER TO tag id_ls
SET KEY TO nlsz
SCAN
- это медленно. Быстрее (и проще) одной командой
Код: plaintext
Scan for id_ls = nlsz
Это при условии, что индекс выглядит как Index on id_ls tag id_ls

3. Если индекс простой, то запрос в девятке должен работать с той же скоростью, что и поиск по индексу. Если это не так - переписывайте условие запроса, чтобы оно точно совпадало с индексным выражением, и сравнивайте Set("collate") и IDXCOLLATE(). Сделав через запрос, вы получите выигрыш в обработке сразу нескольких записей. Ну и теоретически неявное открытие таблиц запросом должно работать чуть быстрее, чем Use (cTable)

4. Медленное открытие таблиц на сервере можно побороть правильной настройкой сети. Кроме того, можно открывать таблицы заранее, при старте приложения, и держать их открытыми. Вы получите единовременное замедление в самом начале, которое окупится при многократном обращении к ним. Для подстаховки можно открывать их только на чтение - USE (cTable) Shared noupdate
...
Рейтинг: 0 / 0
Как ускорить этот цикл? (выборка из архивных файлов по условию)
    #36544452
А. С.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Любой SELECT быстрее выборки SET KEY TO он не будет работать все равно. А таблицы при этом естесственно проиндексирваны.
А вот "Наличие правильных индексов очень сильно ускоряет select" - для меня откровение, нигде не встречал, почитаю.
...
Рейтинг: 0 / 0
Как ускорить этот цикл? (выборка из архивных файлов по условию)
    #36544501
karly™
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
При соблюдении следующих условий
1. VFP 9
2. Индексное выражение точно совпадает с условием запроса
3. Порядок сортировки индекса idxcollate() совпадает с настройкой set collate
3. Кодовая страница таблицы совпадает с cpCurrent()

Select будет работать с той же скоростью, что и поиск по индексу seek или Set key

Почитать, и выполнить сравнительные тесты вы можете здесь http://foxclub.ru/articles/art45.php#example

Напишите точное выражение индекса таблицы, и текст своего запроса, тогда можно будет найти причину замедления.
...
Рейтинг: 0 / 0
Как ускорить этот цикл? (выборка из архивных файлов по условию)
    #36544539
автор2. Связка

SET ORDER TO tag id_ls
SET KEY TO nlsz
SCAN

- это медленно. Быстрее (и проще) одной командой

Scan for id_ls = nlsz

ИМХО,

Код: plaintext
1.
2.
3.
4.
IF SEEK(nlsz)
  DO WHILE id_ls=nlsz
    SKIP
  ENDDO
ENDIF

ещё быстрее.
...
Рейтинг: 0 / 0
Как ускорить этот цикл? (выборка из архивных файлов по условию)
    #36544589
karly™
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ШестипаловIF SEEK(nlsz)
DO WHILE id_ls=nlsz
SKIP
ENDDO
ENDIF

ещё быстрее.Согласен. Полезный прием, если между Do While и EndDo нужно выполнить несколько команд.

Здесь же все можно уложить в один Select
...
Рейтинг: 0 / 0
Как ускорить этот цикл? (выборка из архивных файлов по условию)
    #36544630
karly™Согласен. Полезный прием, если между Do While и EndDo нужно выполнить несколько команд.

Здесь же все можно уложить в один Select

А с этим согласен я :-)
...
Рейтинг: 0 / 0
Как ускорить этот цикл? (выборка из архивных файлов по условию)
    #36544726
А. С.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо за ответы, буду экспериментировать и засекать условия и время выполнения.
...
Рейтинг: 0 / 0
Как ускорить этот цикл? (выборка из архивных файлов по условию)
    #36544911
quxix
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А. С.Привет всем. Есть код, смысл его в том, что есть архивные файлы с оплатой, они находятся в папках для каждого месяца, а месяца разбиты по годам (но это не важно).
дерево такое:
2008
_01\oplata.dbf
_02\oplata.dbf
_03\oplata.dbf
_NN\oplata.dbf
2009
_01\oplata.dbf
_02\oplata.dbf
_03\oplata.dbf
_NN\oplata.dbf
Задача в курсор выбрать из всех таблиц записи по лицевому счету.
Можно ли еще ускорить этот процесс, может есть способы это делать быстрее, чем в приведенном коде?

Может сделать табличку в которой отобразить счета и соотв. им название табл оплат, в соответствии с которой тянуть данные с указанных таблиц. Т.е. не открывать те таблички в которых нет данных по указанному счету.
...
Рейтинг: 0 / 0
Как ускорить этот цикл? (выборка из архивных файлов по условию)
    #36545753
А. С.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ШестипаловIF SEEK(nlsz)
DO WHILE id_ls=nlsz
SKIP
ENDDO
ENDIF

ещё быстрее.

Огромное СПАСИБО! Отрабатывает 40 архивных месяцев меньше 2-х секунд. Решение то на поверхности лежало. Век живи - век учись.
...
Рейтинг: 0 / 0
Как ускорить этот цикл? (выборка из архивных файлов по условию)
    #36546052
karly™
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А. С. Век живи - век учисьНаучившегося использовать индексы в запросах так же ждут приятные открытия ;)
...
Рейтинг: 0 / 0
Как ускорить этот цикл? (выборка из архивных файлов по условию)
    #36546074
А. С.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Да дело в том что программирую на Фоксе достаточно давно, но никогда не думал что в селекте могут использоваться индексы.
...
Рейтинг: 0 / 0
Как ускорить этот цикл? (выборка из архивных файлов по условию)
    #36549723
leaf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
главное найти начало стопки ...
иначе для чого индекс то?
...
Рейтинг: 0 / 0
Как ускорить этот цикл? (выборка из архивных файлов по условию)
    #36552458
Zmej
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ШестипаловИМХО,

IF SEEK(nlsz)
DO WHILE id_ls=nlsz
SKIP
ENDDO
ENDIF

ещё быстрее.
Теоретически:
Код: plaintext
1.
2.
3.
4.
5.
IF SEEK(nlsz)
  SCAN WHILE id_ls=nlsz

  ENDSCAN
ENDIF
должно быть еще быстрее
А вообще - чтобы покороче, то весь кусок:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
				SET ORDER TO tag id_ls
					SET KEY TO nlsz
					SCAN
						SCATTER TO eee
						SELECT cTemp
						APPEND BLANK
						GATHER FROM eee
					ENDSCAN
можно заменить на
Код: plaintext
INSERT INTO cTemp (имяПоля1, имяПоля2,....) SELECT имяПоля1, имяПоля2,.... FROM tmp WHERE tmp.id_ls = nlsz
правда придется перечислять имена полей...
Да, чуть не забыл, для проверки оптимизируемости SQL выражений (если тормозит SELECT) можно использовать функцию SYS(3054). Т.е. где-то так
Код: plaintext
1.
2.
SYS( 3054 , 1 )                   && включаем вывод сообщения об оптимизации на экран
INSERT INTO cTemp (имяПоля1, имяПоля2,....) SELECT имяПоля1, имяПоля2,.... FROM tmp WHERE tmp.id_ls = nlsz
SYS( 3054 , 1 )                   && отключаем
Как Вы понимаете эту функцию нужно использовать только на этапе отладки приложения.
...
Рейтинг: 0 / 0
21 сообщений из 21, страница 1 из 1
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Как ускорить этот цикл? (выборка из архивных файлов по условию)
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]