powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Как можно ускорить поиск в dbf файле ~250000 строк
14 сообщений из 14, страница 1 из 1
Как можно ускорить поиск в dbf файле ~250000 строк
    #37653367
xnik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день всем!
Есть *.dbf файл содержащий ~250000 записей с множеством полей размером ~700 МБ.
Необходимо по значению двух полей найти запись и подставить в Excel значение трех других полей.
Использую VFPODBC. Первоначально при каждом поиске создавал Recordset, а в sql-запросе указывал условие поиска.
Код: vbnet
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.
28.
29.
30.
31.
32.
33.
34.
            Dim strcon2 As String
            Dim strsql2 As String
            Dim cn2 As ADODB.Connection
            Dim rs2 As ADODB.Recordset
            Dim spv As String
            Dim npv As String
            Dim timef As Date
            nLen = Len(Target.Value)
            If (nLen >= 10) Then
                npv = Right(Target.Value, 6)
                spv = Left(Target.Value, nLen - 6)
                strcon2 = "Driver={Microsoft Visual FoxPro Driver};UID=;SourceType=DBF;Exclusive=No;Background-dFetch=Yes;Collate=Russian;Null=No;Deleted=Yes;SourceDB=c:\xx\Basa;"
                Set cn2 = New ADODB.Connection
                cn2.ConnectionString = strcon2
                cn2.Open
                strsql2 = "select R24, R25, R26 from vxxx.dbf where r55='" & spv & "' and r56='" & npv & "'"
                Set rs2 = New ADODB.Recordset
                
                timef = Time()
                rs2.Open strsql2, cn2, adOpenKeyset, adLockOptimistic
                timef = Time() - timef
                Application.StatusBar = "Готово. Время выполнения: " & timef

                Do Until rs2.EOF
                    Cells(Target.Row, 10).Value = Trim(rs2.Fields("R24").Value)
                    Cells(Target.Row, 11).Value = Trim(rs2.Fields("R25").Value)
                    Cells(Target.Row, 12).Value = Trim(rs2.Fields("R26").Value)
                    rs2.MoveNext
                Loop
                rs2.Close
                cn2.Close
                Set rs2 = Nothing
                Set rs2 = Nothing
            End If


Время выполнения запроса на Atom N270 1GB RAM - от 20 до 40 секунд.

Сейчас открываю Recordset с SQL запросом без условия при открытии документа. А ищу нужную запись накладыванием фильтра на Recordset.
Код: vbnet
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.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
Private Sub Workbook_Open()
    Dim ConnectionString2 As String
    Dim SQLString2 As String
    Dim TimeFlag As Date
    
    ConnectionString2 = "Driver={Microsoft Visual FoxPro Driver};UID=;SourceType=DBF;Exclusive=No;Background-dFetch=Yes;Collate=Russian;Null=No;Deleted=Yes;SourceDB=c:\xx\Basa;"
    SQLString2 = "select R24, R25, R26, R55, R56 from vxxx.dbf order by r55, r56"
    Set rs2 = New ADODB.Recordset
    
    Application.DisplayStatusBar = True
    Application.StatusBar = "Открываем набор записей!"
    Application.ScreenUpdating = False
                
    TimeFlag = Time()
    With rs2
        .CursorType = adOpenKeyset
        .LockType = adLockReadOnly
        .Open SQLString2, ConnectionString2, adCmdText
    End With
    TimeFlag = Time() - TimeFlag
                
    Application.StatusBar = "Время открытия набора записей: " & TimeFlag
    Application.ScreenUpdating = True
End Sub

Private Sub Worksheet_Change(ByVal Target As Range)
    If (Target.Count = 1) Then
        If (Target.Column = 14 And Target.Value <> "") Then
            Dim spv As String
            Dim npv As String
            Dim timef As Date
            nLen = Len(Target.Value)
            If (nLen >= 10) Then
                npv = Right(Target.Value, 6)
                spv = Left(Target.Value, nLen - 6)

                timef = Time()    
                rs2.Filter = "r55='" & spv & "' AND r56='" & npv & "'"
                timef = Time() - timef
                
                Application.StatusBar = "Готово. Время выполнения: " & timef
                Application.ScreenUpdating = True
                'MsgBox rs2.GetString
                Do Until rs2.EOF
                    Cells(Target.Row, 10).Value = Trim(rs2.Fields("R24").Value)
                    Cells(Target.Row, 11).Value = Trim(rs2.Fields("R25").Value)
                    Cells(Target.Row, 12).Value = Trim(rs2.Fields("R26").Value)
                    rs2.MoveNext
                Loop
            End If
        End If
    End If
End Sub


Документ дольше открывается, занимает больше памяти. Но поиск записи выполняется за ~8 секунд.
Есть ещё одна таблица, по объёму в два раза больше, количество записей не знаю. По второй таблице поиск осуществляется за ~15 секунд.
Как можно ускорить поиск в *.dbf?
Как указать индексный файл при использовании VFPODBC? Наличие файла ускорит поиск в первоначальном варианте?
При положительном ответе на предыдущий вопрос, как создать индексный файл VBS-скриптом с использованием VFPODBC драйвера?
...
Рейтинг: 0 / 0
Как можно ускорить поиск в dbf файле ~250000 строк
    #37653371
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
При таком объеме данных стоит подумать об их переносе в более шуструю бд, если условия это позволяют.
...
Рейтинг: 0 / 0
Как можно ускорить поиск в dbf файле ~250000 строк
    #37653378
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вообще это больше вопрос по тонкостям dbf, чем VB, вам лучше сюда обратиться.
...
Рейтинг: 0 / 0
Как можно ускорить поиск в dbf файле ~250000 строк
    #37653464
Фотография ПЕНСИОНЕРКА
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
xnik,

Есть *.dbf файл содержащий ~250000 записей с множеством полей размером ~700 МБ.
это примерно 3000б на запись

strsql2 = "select R24, R25, R26 from vxxx.dbf where r55='" & spv & "' and r56='" & npv & "'"
а сколько занимают r24-r25-r26
похоже r55+r56 примерно 10 типа 55555-666666

в одной из задач перегоняла DBF в MDB по запросу пользователя(обновление таблицы)
поиск и расчеты уже проводились в MDB на фиксированном на дату-время массиве
...
Рейтинг: 0 / 0
Как можно ускорить поиск в dbf файле ~250000 строк
    #37654908
Фотография AndreTM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
xnik,

покажите тип и размерность R55, R56
покажите пример данных в этих полях в таблице
покажите пример spv и npv (или Target.Value )

или так:
Код: sql
1.
strsql2 = "select R24, R25, R26 from vxxx.dbf where left(r55,5)='" & spv & "' and left(r56,6)='" & npv & "'"
...
Рейтинг: 0 / 0
Как можно ускорить поиск в dbf файле ~250000 строк
    #37655195
xnik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
To AndreTM:
Поле R55 - СНАRACTER длина 4, поле R56 - CHARACTER длина 6.
Target.Value - серия и номер документа, например 50АА012345.

To ПЕНСИОНЕРКА:
Поля R24, R25, R26 - CHARACTER длина 20.
Во втором варианте Recordset уже в памяти, загружены только необходимые данные.
Время поиска в mdb файле будет меньше, чем выполнение Recordset.Filter?
Я думал о таком варианте: перенос по запросу только необходимых данных в дополнительную базу и поиск по новой базе. Буду пробовать.
...
Рейтинг: 0 / 0
Как можно ускорить поиск в dbf файле ~250000 строк
    #37655201
Фотография HandKot
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
для ускорения поиска нужны индексы.
они даже есть в ДБФ, но вот как с ними работать через АДО не скажу
надо порытся на форуме ДБФ
...
Рейтинг: 0 / 0
Как можно ускорить поиск в dbf файле ~250000 строк
    #37656673
Фотография AndreTM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
xnik,
что-то я недопонимаю во фразе If (nLen >= 10) Then ...
если Len(npv)=6, то от spv надо искать не более 4 символов, ибо всё равно Len(r55)=4
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
pv = Trim(Target.Value)
If Len(pv) >= 10 Then
 npv = Right(pv, 6)
 spv = Left(pv, 4)
' ...
 strsql2 = "select R24, R25, R26 from vxxx.dbf where r55=='" & spv & "' and r56=='" & npv & "'"
' ...
...
Рейтинг: 0 / 0
Как можно ускорить поиск в dbf файле ~250000 строк
    #37656690
xnik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
AndreTM,
Правильно будет поставить условие If Len(pv) = 10. Моя ошибка.
Защиту от некорректного ввода ещё не делал.

Добавлю, следующее: к файлу *.dbf есть одноименный индексный файл *.cdx. Наличие файла в одной директории с таблицей не уменьшает время поиска, по нужным полям. Может они не входят ни в один индекс. Поиск по полю R24 (содержит фамилию, определенно должно быть одним из индексов) занимает примерно одинаковое время без индексного файла и с ним, даже с включением сортировки по этому полю. Я думал, что простое наличие индексного файла определяется VFPODBC. Сама база не открывается редактором DBF, чтобы посмотреть индексы.
Как перенести тему в ветку по FoxPro? Может там подскажут?
...
Рейтинг: 0 / 0
Как можно ускорить поиск в dbf файле ~250000 строк
    #37656755
Фотография AndreTM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вряд ли наличие индекса поможет - ADO индексы Фокса не пользует. Быстродействие же выборок внутри самого Фокса базируется на Рашморе, - естественно, это внутреннаяя технология.
Как вариант - сделать одно суммарное поле "серия+номер" и выбирать только не му, но это вряд ли даст сильный прирост быстродействия. Если вам действительно требуется постоянное соединение со справочником - вариант вам был подсказан Пенсионеркой.

Еще вопрос - а зачем каждый раз делать выборку? Во втором варианте вы как бы сначала действуете правильно - одноразово забираете справочник, но затем - зачем именно фильтрация-то? Есть же .Find(), .Seek() (ведь можно и Index для рекордсета создать)

На вашем же месте я бы поменял инструмент. Как я понимаю, сейчас вы по реквизитам документа находите в таблице нужные вам данные - и вписываете их. При этом "справочник" персоналий не меняется (или меняется не "на ходу"). Ну так вам прямо подсказано - реализуйте свою задачу на Access. Иначе вам (если вы не надеетесь на быстродействие встроенных методов) для ускорения поиска все равно придется делать в Excel'е что-то вроде индексов - например, преобразовывать таблицу в дерево поиска посимвольно...
...
Рейтинг: 0 / 0
Как можно ускорить поиск в dbf файле ~250000 строк
    #37656962
xnik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
AndreTM,
Вы правильно поняли задачу.
Find - осуществляет поиск только по одному полю. Filter можно сделать по нескольким полям. Пробовал сделать сначала Find по номеру, а затем перебором найти запись с нужной серией. Find по номеру длится дольше, чем Filter сразу по двум полям. Для функции Seek создать программно индекс не пытался.
Буду делать с помощью промежуточной базы Access. Может будет быстрее, чем Filter на Recordset'е.
Спасибо, за ответы.
...
Рейтинг: 0 / 0
Как можно ускорить поиск в dbf файле ~250000 строк
    #37657054
Guest33
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Попробуйте (не знаю, получится или нет) построить индекс для АДО рекордсета (уже должен быть открыт) по нужному полю, типа:
Код: vbnet
1.
rst!field1.Properties("Optimize") = True
...
Рейтинг: 0 / 0
Как можно ускорить поиск в dbf файле ~250000 строк
    #37657346
Фотография AndreTM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
xnikFind - осуществляет поиск только по одному полю...И что? Вы Select-SQL вообще не знаете? Сложно сделать:
Код: vbnet
1.
select R24, R25, R26, r55+r56 as r55_56 from vxxx.dbf

и затем использовать
Код: vbnet
1.
.Find "r55_56='" & spv & npv & "'"


Индекс ведь тоже надо делать по нескольким полям...
...
Рейтинг: 0 / 0
Как можно ускорить поиск в dbf файле ~250000 строк
    #37790322
Puritanin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
а как Вы подключаете индексы для SQL сервера например...Язык то один и тот же
where XXXXXXXXXX order by XXXXX.....это и есть подключение индекса
...
Рейтинг: 0 / 0
14 сообщений из 14, страница 1 из 1
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Как можно ускорить поиск в dbf файле ~250000 строк
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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