![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Ускорить работу с БД
Ega23 © (2009-02-27 15:57:00)1. Postgres 8.2, Postgres ANSI ODBC Driver
2. Delphi 7, TADODataSet
Смысл такой.
На сервере создаётся абсолютно тупая таблица:
create table test_tbl (
unid int4 not null default nextval('seq_test_unid'::regclass),
aname varchar(32) not null,
lastupdated timestamp not null default 'cast(now() as timestamp)',
constraint pk_test_tbl primary key (unid)
);
Дальше она тупо заполняется, 100.000 записей (aname - IntToStr(Random(....))
Есть следующие классы:
TSimpleRecord = class (TObject)
public
ID : Integer;
Name : string;
constructor Create(ads : TADODataSet);
end;
TSimleRecordList = class (TObjectList)
private
function GetItem(Index: Integer): TSimpleRecord;
public
property Items[Index : Integer] : TSimpleRecord read GetItem;
procedure LoadFromDataSet(ads : TADODataSet);
end;
{ TSimpleRecord }
//*****************************************************************************
constructor TSimpleRecord.Create(ads: TADODataSet);
begin
ID := ads.FieldByName('unid').AsInteger;
Name := ads.FieldByName('aname').AsString;
end;
//*****************************************************************************
{ TSimleRecordList }
//*****************************************************************************
function TSimleRecordList.GetItem(Index: Integer): TSimpleRecord;
begin
Result := TSimpleRecord(inherited GetItem(Index));
end;
//*****************************************************************************
procedure TSimleRecordList.LoadFromDataSet(ads: TADODataSet);
begin
if ads.IsEmpty then Exit;
ads.First;
while not ads.Eof do
begin
Add(TSimpleRecord.Create(ads));
ads.Next;
end;
end;
Делаю select * from и результат загоняю в лист.
Так вот, само открытие и передача данных происходит ~ за 3 секунды. А вот наполнение листа ~ 170 секунд.
Вопрос: а можно ли это дело как-то ускорить?
З.Ы. Заранее предупреждая замечания "нефиг тащить столько записей на клиент" - я в курсе, что столько нельзя. Вот только пользователи не в курсе и фильтрами не любят пользоваться. В любом случае в данный момент это просто исследование.
Ega23 (2009-02-28 16:42:00) [1]
> Что вы такой недотрога, если у вас -"нужно ровно то, что
> нужно мне", зачем тут спрашивать? базар он и есть базар,
> т.е. форум как часто говорит Anatoly Podgoretsky.
Гм... Мне казалось, что я вопрос сформулировал предельно чётко.
> считаю, что вам надо голубой значок!
Я так не считаю, есть гораздо более достойные кандидаты.
b z (2009-02-28 13:57:00) [2]
> Ega23 ©
Дабы скрасить и все такое :) считаю, что вам надо голубой значок! (ИМХО, хотя и против "ИМХО" как такового)
b z (2009-02-28 12:26:00) [3]
> Знаете, с советами "идите в дотнет"
Тем более, что это не отменяет Delphi. :)
b z (2009-02-28 12:22:00) [4]
> Ega23 © (28.02.09 12:07) [15]
Что вы такой недотрога, если у вас -"нужно ровно то, что нужно мне", зачем тут спрашивать? базар он и есть базар, т.е. форум как часто говорит Anatoly Podgoretsky.
Ega23 (2009-02-28 12:07:00) [5]
> Здесь не надо приватных полей, раз уж передали датасет,
> то и продолжайте по средствам инкапсуляции работать с ним.
Здесь нужно ровно то, что нужно мне.
> идите в .NET, там уже и этого не надо. :)
Знаете, с советами "идите в дотнет", "пишите на джаве", "Postgres - г..но, используйте Oracle" и т.п. - идите на сайт к Каганову.
b z (2009-02-28 11:27:00) [6]
> constructor TSimpleRecord.Create(ads: TADODataSet);
> begin
> ID := ads.FieldByName('unid').AsInteger;
> Name := ads.FieldByName('aname').AsString;
> end;
Здесь не надо приватных полей, раз уж передали датасет, то и продолжайте по средствам инкапсуляции работать с ним.
А ..., если вы хотите типа своего орма, идите в .NET, там уже и этого не надо. :)
Ega23 (2009-02-28 10:47:00) [7]
> а еще больше если никуда данные не переносить, а так и держать
> локально/работь и ними в рекордсете... это же готовая структура
> для данных, нафига перекладывания?
Так я же и говорю: как раз research провожу. Пробую всякие разные способы.
Palladin (2009-02-27 18:36:00) [8]ну... то что я сказал больше справедливо для трех и более звенных приложений... ) которые пытаются не быть зависимыми от СУБД в частности и АДО в целом )
sniknik (2009-02-27 18:12:00) [9]> ну... у простого (или хитрого, с отсортированными id и бинарным поиском по ним) списка доступ к данным быстрее...
думаешь? ... мы тут как то "мерялись" сортировкой по id c "супербыстрым" стринглистом специально заточенным под это... и в общем разница была небольшая. т.е. в первый раз небольшая (ADODataSet проиграл), а второй и последующие разы ADODataSet просто подключал уже готовый индекс (время соответственно = 0), а стриглист давал тоже самое, хотя надо признать довольно маленькое время.
> и словари так кэшировать на клиенте проще...
? после запроса с локальным курсором, рекордсет практически готовый кэш, куда проще то?
Palladin (2009-02-27 17:43:00) [10]
> это же готовая структура для данных, нафига перекладывания?
ну... у простого (или хитрого, с отсортированными id и бинарным поиском по ним) списка доступ к данным быстрее... и словари так кэшировать на клиенте проще...
sniknik (2009-02-27 17:33:00) [11]> Посчитал, что если никаких DataSource с ним не связано
ну ты тут не одинок Игорь Шевченко там вон тоже считает, что внутренние проверки отключать не надо...
+ у тебя еще можно выиграть "пару тройку милисекунд" если вынести поиск объектов полей ads.FieldByName('unid'), ads.FieldByName('aname') за цикл.
а еще больше если никуда данные не переносить, а так и держать локально/работь и ними в рекордсете... это же готовая структура для данных, нафига перекладывания?
Ega23 (2009-02-27 17:09:00) [12]
> Выставь, перед выполнением запроса, свойства датасета
А вот эти дела только хуже сделали. Хотя - странно.
На выходных дома поэксперементирую более серьёзно. Но тут у меня уже на драйвер постгресовский подозрение...
Ega23 (2009-02-27 16:31:00) [13]
> sniknik © (27.02.09 16:28) [4]
Ага, это я уже косяк упорол. Посчитал, что если никаких DataSource с ним не связано, то и фиг с ним. Но чтобы ТАКОЙ прирост производительности - не ожидал, чесслово!
Palladin (2009-02-27 16:30:00) [14]
> ЁПРСТ!
хе :)...
Ega23 (2009-02-27 16:29:00) [15]ЁПРСТ!
procedure TSimleRecordList.LoadFromDataSet(ads: TADODataSet);
begin
if ads.IsEmpty then Exit;
ads.DisableControls;
try
ads.First;
while not ads.Eof do
begin
Add(TSimpleRecord.Create(ads));
ads.Next;
end;
finally
ads.EnableControls;
end;
end;
Ускорение на 2 порядка.
Сейчас с курсорами поиграюсь, может ещё что-то выжму...
sniknik (2009-02-27 16:28:00) [16]
procedure TSimleRecordList.LoadFromDataSet(ads: TADODataSet);
begin
if ads.IsEmpty then Exit;
ads.First;
while not ads.Eof do
begin
Add(TSimpleRecord.Create(ads));
ads.Next;
end;
end;
http://www.delphimaster.ru/cgi-bin/forum.pl?id=1235121964&n=18
Ega23 (2009-02-27 16:25:00) [17]
> с чего решение, что данные ПЕРЕДАЛИСЬ?
> они передаются там, где "170 секунд".. данные все сразу
> не фетчатся.. сделай FetchAll (если есть такой метод) или
> Last/First
Да я как-бы не первый день замужем, это проверил в первую очередь.
З.Ы. Сам удивлён безмерно. Вроде бы тупая операция - обойти датасет...
Palladin (2009-02-27 16:23:00) [18]Выставь, перед выполнением запроса, свойства датасета
CursorLocation:=clUseServer;
CursorType:=ctOpenForwardOnly;
LockType:=ltReadOnly;
и сравни
Виталий Панасенко (2009-02-27 16:12:00) [19]
> Так вот, само открытие и передача данных происходит ~ за
> 3 секунды.
с чего решение, что данные ПЕРЕДАЛИСЬ?
они передаются там, где "170 секунд".. данные все сразу не фетчатся.. сделай FetchAll (если есть такой метод) или Last/First