![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Быстая работа с большой базой [D6]
ZedeS © (2005-09-30 17:01:00)Доброго времени суток.
Проблема следующего характера:
Надо за приемлемое время (1-2 мин) обработать (прочитать значения 5 полей и произвести нехитрые вычисления)приблизительно 1 млн. записей.
Сейчас использую Delphi и Access через ADO.
На P4 2.4G и 512Mb - 100 000 записей обрабатывается за 2,5 мин
Чем лучше заменить Access или надо вводить многопоточность.
Заранее благодарен
eJack (2005-10-07 05:47:00) [1]Попробуй сжать базу перед работай
procedure CompactDatabase_JRO(DatabaseName: string; DestDatabaseName: string =
''; Password: string = '');
const
Provider = 'Provider=Microsoft.Jet.OLEDB.4.0;';
var
TempName: array[0..MAX_PATH] of Char; // имя временного файла
TempPath: string; // путь до него
Name: string;
Src, Dest: WideString;
V: Variant;
begin
try
Src := Provider + 'Data Source=' + DatabaseName;
if DestDatabaseName <> '' then
Name := DestDatabaseName
else
begin
// выходная база не указана - используем временный файл
// получаем путь для временного файла
TempPath := ExtractFilePath(DatabaseName);
if TempPath = '' then
TempPath := GetCurrentDir;
//получаем имя временного файла
GetTempFileName(PChar(TempPath), 'mdb', 0, TempName);
Name := StrPas(TempName);
end;
DeleteFile(PChar(Name)); // этого файла не должно существовать :))
Dest := Provider + 'Data Source=' + Name;
if Password <> '' then
begin
Src := Src + ';Jet OLEDB:Database Password=' + Password;
Dest := Dest + ';Jet OLEDB:Database Password=' + Password;
end;
V := CreateOleObject('jro.JetEngine');
try
V.CompactDatabase(Src, Dest); // сжимаем
finally
V := 0;
end;
if DestDatabaseName = '' then
begin // т.к. выходная база не указана
DeleteFile(PChar(DatabaseName)); //то удаляем не упакованную базу
RenameFile(Name, DatabaseName); // и переименовываем упакованную базу
end;
except
// выдаем сообщение об исключительной ситуации
on E: Exception do
ShowMessage(e.message);
end;
end;
И незабывай про индескы, создай их динамически (если их нет), а потом удали, если они не нужны. И все будет ОК.
Карелин Артем (2005-10-05 17:28:00) [2]
> msguns © (05.10.05 14:43) [35]
Отвечу вопросами на вопрос :)
1) Зачем использовать набор данных, загружающий всю инфу в память на клиенте, если нет необходимости в Data-aware компонентах?
2) Зачем использовать компонент, работающий как минимум на порядок медленнее?
Если у меня в случае TIBSQL ушло полгига под прочитанные данные, то сколько уйдет еще и при перемещении набора данных в конец? Про UniDirectional ни строчки не было ;)
msguns (2005-10-05 14:43:00) [3]>Карелин Артем © (05.10.05 11:54) [32]
>Ты случаем не спутал Dataset с TIBSQL???
Нет, не спутал. Перефразирую вопрос:
Зачем для получения НД на клиенте используется TIBSQL вместо куда более удобных для этой цели TIBDataSet или, если НД не требуется редактировать, TIBQuery с методом Open ?
Возможно, ты посчитаешь это придиркой, но ведь на замечание АП о "страшности" кода сам же полез на рожон, чем и вызвал критику приведенного тобоюкода ;)
Seg (2005-10-05 12:15:00) [4]А может взять Оракл и курсором прочитать все записи?
Карелин Артем (2005-10-05 12:04:00) [5]Насчет переменной каюсь - неаккуратно вырезал часть кода из общей кучи.
Карелин Артем (2005-10-05 11:54:00) [6]
> msguns © (05.10.05 09:18) [27]
> 1. Почему для селекта исп-ся ExecSQL ?
> 4. Нет инициализации j, да и вообще не понятно, нафиг она
> нужна, если общее число записей после сигнала EOF можно
> получить из RecordCount
Ты случаем не спутал Dataset с TIBSQL???
> 2. Нет обработки ошибок
На фига это тут? Это же не реально используемый код.
> sniknik © (05.10.05 11:00) [29]
Почитай строку 1 моего поста и посмотри куда она ссылается. Проделав все это может и поймешь к чему я писал.
Все нормально работает, 500 мегов примерно памяти хавает в процессе.
Развернутый блин вывод из теста:
1) Как можно заметить, данные из базы в случае использования самых легких и некэширующих компонентов загружаются со скоростью вжика.
2) Проблема в TSringGrid и кэшировании на клиенте.
Anatoly Podgoretsky (2005-10-05 11:36:00) [7]Карелин Артем © (05.10.05 09:03) [26]
Нехорошо, что для измерения скорости ты привлек сюда зачем то TSringList, c которым работаешь самым неоптимальным путем, постоянно перераспределяешь память.
Ты что хочел замерить скорость заполнения TSringList, а вопрос то про базу. Кроме того у автора TSringGrid, что на порядке хуже.
ANB (2005-10-05 11:14:00) [8]
> Zedes © (04.10.05 16:33) [18]
В принципе и акссес умеет с SQL работать. Зачем считывать все данные на клиента - не очень понятно - уйдет уйма оперативки и ессно будет тормозить.
Решение :
1. Довесить на таблицу индексы
2. Написать нормальный SQL запрос (смотреть sum, count, group by, where, iif)
Все должно довольно шустро обработаться.
sniknik (2005-10-05 11:00:00) [9]Карелин Артем © (04.10.05 19:39) [24]
ну во первых у автора не StringList а StringGrid, обращения к которому на порядок медленнее, добавления не "интелектуальны" (нет блочного выделения памяти "наперед"), и каждая строка грида есть список (у тебя создается только один). + вполне вероятно что кроме всего прочего грид у него отображается на форме в момент вдобавлений...
т.е. твое сравнение в "корне неправильное".
вывод "БД тут не причем." верен, но непонятно (в свете теста) на чем основан.
а во вторых добавленные значения после нигде не используются... на месте оптимизатора я бы его вообще выкинул из данного кода нафиг ;), всю переменную s. но как там на самом деле смотреть не хочется.
msguns (2005-10-05 09:20:00) [10]5 пункт прошу не читать. Глючнуло ;)))
msguns (2005-10-05 09:18:00) [11]>Карелин Артем © (05.10.05 09:03) [26]
>А что такого нехорошего? Обращение по номеру поля? Так это чисто для скорости.
1. Почему для селекта исп-ся ExecSQL ?
2. Нет обработки ошибок
3. Общий стиль: эти Button1, IBSQL1
4. Нет инициализации j, да и вообще не понятно, нафиг она нужна, если общее число записей после сигнала EOF можно получить из RecordCount
5. Совершенно неясно, что тут делает стрингрид, который нигде на экране не присутствует.
Карелин Артем (2005-10-05 09:03:00) [12]
> Anatoly Podgoretsky © (04.10.05 20:03) [25]
А что такого нехорошего? Обращение по номеру поля? Так это чисто для скорости.
Anatoly Podgoretsky (2005-10-04 20:03:00) [13]Бр, какой не хороший код. Измеряй без S.Add(IBSQL1.Fields[3].AsString);
Карелин Артем (2005-10-04 19:39:00) [14]
> Zedes © (04.10.05 16:50) [20]
БД тут не причем. Следующий код на 1 746 229 записях выполняется 4 секунды на Firebird.
procedure TForm1.Button1Click(Sender: TObject);
var s:TStringList;
i,j:integer;
begin
i:=GetTickCount;
s:=TStringList.Create;
IBSQL1.ExecQuery;
while not(IBSQL1.Eof) do
begin
S.Add(IBSQL1.Fields[3].AsString);
IBSQL1.Next;
inc(j);
end;
ShowMessage(IntToStr(GetTickCount-i)+' '+IntToStr(j));
s.Free;
end;
Anatoly Podgoretsky (2005-10-04 17:10:00) [15]sniknik © (04.10.05 16:42) [19]
Много хуже, я такого даже и предположить не мог.
Anatoly Podgoretsky (2005-10-04 17:08:00) [16]Zedes © (04.10.05 16:50) [20]
TStringGrid служит для визуализации!!!
Виталий Панасенко (2005-10-04 16:59:00) [17]
> Zedes © (04.10.05 16:50) [20]
> Тест показал, что почти все время тратится на чтение записей
> из БД.
> 200 000 записей читаются в StringGrid приблизительно 8 мин,
> а дальнейшая обработка занимает 40 сек.
А на кой в StringGrid ? И вообще, нужно ли СНАЧАЛА ЧИТАТЬ, А ПОТОМ ОБРАБАТЫВАТЬ ? Может, одновременно лучше ? Т.е. ПО МЕРЕ СЧИТЫВАНИЯ ? Настройки подключения (особенно, CursorLocation.. Установи "на сервере")
Zedes (2005-10-04 16:50:00) [18]Тест показал, что почти все время тратится на чтение записей из БД.
200 000 записей читаются в StringGrid приблизительно 8 мин, а дальнейшая обработка занимает 40 сек.
В этом проекете БД не инструмент, а способ собрать (и не потерять) записи, за определенный период времени. Никакой предварительной обработки (при добавлении в БД например) не получается, поэтому ни триггеры, ни хранимые процедуры, ни автовычисляемы поля никуда не приткнеш.
Нужно чтобы приложение бысто считывало инфу из базы.
Какую БД взять (либо дешевую, либо free)?
sniknik (2005-10-04 16:42:00) [19]app © (30.09.05 19:57) [10]
> Zedes © (30.09.05 17:44) [7]
> Намек на навигационные методы понят.
оказалось все гораздо "хужее" ;) ->
Zedes © (04.10.05 16:33) [18]
> 200 000 записей читаются в StringGridприблизительно 8 мин.
> Какую БД взять (либо дешевую, либо free)?
любую. с такими подходами тормоза неизбежны, на любойбазе... но можно решить "железно", т.е. перенести задачу на суперкомпьютер (крей или как там их зовут)... ;о))
Zedes (2005-10-04 16:33:00) [20]Тест показал, что почти все время тратится на чтение записей из БД.
200 000 записей читаются в StringGrid приблизительно 8 мин, а дальнейшая обработка занимает 40 сек.
В этом проекете БД не инструмент, а способ собрать (и не потерять) записи, за определенный период времени. Никакой предварительной обработки (при добавлении в БД например) не получается, поэтому ни триггеры, ни хранимые процедуры, ни автовычисляемы поля никуда не приткнеш.
Нужно чтобы приложение бысто считывало инфу из базы.
Какую БД взять (либо дешевую, либо free)?