Начало » Использование СУБД » Firebird, HQbird, InterBase » IBX: буферизация записей
|
Re: IBX: буферизация записей [сообщение #1508 является ответом на сообщение #1506] |
Sun, 29 January 2023 11:41 |
|
Док
Сообщений: 101 Зарегистрирован: June 2022
|
Senior Member |
|
|
МорскойДесант писал(а) Sun, 29 January 2023 03:36Что-то меня сомнения терзать начали.
А скажи, что значит "дерево загружается"? Ты что, записи из мемдатасета ещё и "внутрь" дерева переносишь?
Покажи, если не жалко.
Не жалко, за свой говнокод стыдно
По поводу мемдатасета - это просто кеш, с которым можно делать все, что угодно. И заполняется он достаточно быстро. И главное, это не визуальный компонент(можно работать в доп.потоке без прокладок) и не требует коннекта для доступа к БД.
Я попробовал загрузку напрямую из IBSQL в дерево.
Начало:
const
MinCount = 100000;
var
Form1: TForm1;
implementation
...
procedure TForm1.Button2Click(Sender: TObject);
var
ExecSQL: TIBSQL = Nil;
startTick: PtrInt = 0;
endTick: PtrInt = 0;
MyThread: TMyThread = nil;
i: Integer;
rNode: PVirtualNode = nil;
rNodeData: PMyRec = nil;
begin
for i:= 0 to Pred(StatusBar1.Panels.Count) do
StatusBar1.Panels[i].Text:= '';
if not IBDatabase1.Connected then IBDatabase1.Connected:= True;
ExecSQL:= TIBSQL.Create(Self);
try
try
startTick:= GetTickCount64;
IBTransaction1.StartTransaction;
ExecSQL.Database:= IBDatabase1;
ExecSQL.Transaction:= IBTransaction1;
ExecSQL.SQL.Text:= 'SELECT COUNT(ID) CNT FROM TEST';
ExecSQL.ExecQuery;
if (ExecSQL.FieldByName('CNT').AsInteger > MinCount) then
begin
MyThread:= TMyThread.Create(True);
MyThread.Start;
end;
ExecSQL.SQL.Text:= 'SELECT ID, NAME FROM TEST';
ExecSQL.ExecQuery;
VST_partial.BeginUpdate;
try
VST_partial.Clear;
while (ExecSQL.RecordCount < Succ(MinCount)) do
begin
rNode:= VST_partial.AddChild(nil);
rNodeData:= VST_partial.GetNodeData(rNode);
rNodeData^.ID:= ExecSQL.FieldByName('ID').AsInteger;
rNodeData^.Name:= ExecSQL.FieldByName('NAME').AsString;
VST_partial.AddChild(rNode);
ExecSQL.Next;
end;
finally
VST_partial.EndUpdate;
VST_partial.ScrollIntoView(rNode,True);
VST_partial.AddToSelection(rNode);
VST_partial.Expanded[rNode]:= False;
end;
endTick:= GetTickCount64;
StatusBar1.Panels[0].Text:= Format('Executing time of inserting %d records into the VST_partial is %d msec',
[MinCount, (endTick - startTick)]);
StatusBar1.Panels[0].Width:= StatusBar1.Canvas.TextWidth(StatusBar1.Panels[0].Text)
+ StatusBar1.Canvas.TextWidth('W');
IBTransaction1.Commit;
except
on E:Exception do
begin
IBTransaction1.Rollback;
{$IFDEF MSWINDOWS}
ShowMessage(WinCPToUTF8(E.Message));
{$ELSE}
ShowMessage(E.Message);
{$ENDIF}
end;
end;
finally
FreeAndNil(ExecSQL);
end;
end;
Доп.поток:
procedure TMyThread.Execute;
begin
try
if not Fdbase.Connected then Fdbase.Connected:= True;
FTrans.StartTransaction;
FexecSQL.ExecQuery;//SQL.Text:= 'SELECT ID, NAME FROM TEST';
Form1.VST_full.Clear;
while not FexecSQL.Eof do
begin
Synchronize(@AddNodeToExtVST);
Sleep(1);
FexecSQL.Next;
end;
FTrans.Commit;
except
on E:Exception do
begin
FTrans.Rollback;
{$IFDEF MSWINDOWS}
ShowMessage(WinCPToUTF8(E.Message));
{$ELSE}
ShowMessage(E.Message);
{$ENDIF}
end;
end;
end;
procedure TMyThread.AddNodeToExtVST;
var
aNode: PVirtualNode = nil;
aNodeData: PMyRec = nil;
begin
with Form1 do
begin
//VST_full.BeginUpdate;
try
aNode:= VST_full.AddChild(nil);
aNodeData:= VST_full.GetNodeData(aNode);
if Assigned(aNodeData) then
begin
aNodeData^.ID:= FexecSQL.FieldByName('ID').AsInteger;
aNodeData^.Name:= FexecSQL.FieldByName('NAME').AsString;
VST_full.AddChild(aNode);
end;
finally
//VST_full.EndUpdate;
//VST_full.ScrollIntoView(aNode,True);
end;
end;
end;
Справа дерево заполняется в потоке
-
Вложение: vst_1.gif
(Размер: 241.79KB, Загружено 1648 раз)
FPC/Lazarus (trunk) | Win10 x64 Ultim/Debian 11 amd64/Darwin x86_64 Monterey | Firebird 3.0.10 x64 | IBX by TonyWhyman
https://zoltanleo.blogspot.com/
[Обновления: Sun, 29 January 2023 12:40] Известить модератора
|
|
|
|
|
|
|
|
Re: IBX: буферизация записей [сообщение #1516 является ответом на сообщение #1515] |
Mon, 30 January 2023 18:26 |
Сообщений: 197 Зарегистрирован: September 2022
|
Senior Member |
|
|
>нет там мемдатасета.
TIBSQL, точно, я невнимателен.
>Насчёт дерева: покажи, как правильно?
Выше писал:
Цитата:
сообщаешь ему, что у тебя в выборке 1 млн записей. Этого достаточно, чтобы дерево правильно отображало скролл.
Дерево хочет показать тебе данные и сразу выдает коллбэк: "А покажи мне данные узлов номер 1, 2, 3 ... <номер последнего видимого узла>".
Т.е., ты не загружаешь в NodeData, не создаешь список в самом vst, а сообщаешь ему, что "вот столько узлов", и всё. А при отображении, vst запрашивает подробности.
|
|
|
Re: IBX: буферизация записей [сообщение #1524 является ответом на сообщение #1516] |
Wed, 01 February 2023 15:36 |
|
Док
Сообщений: 101 Зарегистрирован: June 2022
|
Senior Member |
|
|
МорскойДесант писал(а) Mon, 30 January 2023 18:26Т.е., ты не загружаешь в NodeData, не создаешь список в самом vst, а сообщаешь ему, что "вот столько узлов", и всё. А при отображении, vst запрашивает подробности.
Вообще-то, я ждал от тебя пример кода, хотя бы схематично. В результате, пришлось, как обычно, делать самому о_О
Сорцы сложил сюда
https://bitbucket.org/zoltanleo/vtv_fill/src/main/
-
Вложение: vst_2.gif
(Размер: 96.50KB, Загружено 1458 раз)
FPC/Lazarus (trunk) | Win10 x64 Ultim/Debian 11 amd64/Darwin x86_64 Monterey | Firebird 3.0.10 x64 | IBX by TonyWhyman
https://zoltanleo.blogspot.com/
|
|
|
Re: IBX: буферизация записей [сообщение #1527 является ответом на сообщение #1524] |
Wed, 01 February 2023 18:04 |
Сообщений: 197 Зарегистрирован: September 2022
|
Senior Member |
|
|
Док писал(а) Wed, 01 February 2023 15:36МорскойДесант писал(а) Mon, 30 January 2023 18:26Т.е., ты не загружаешь в NodeData, не создаешь список в самом vst, а сообщаешь ему, что "вот столько узлов", и всё. А при отображении, vst запрашивает подробности.
Вообще-то, я ждал от тебя пример кода, хотя бы схематично. В результате, пришлось, как обычно, делать самому о_О
...
Ну, хорошо. Смотри аттачмент tstVST.7z.
Streets.fbk - архив файла базы, восстановишь сам. Две таблички: city (id, name) и street (id, city_id, name).
Выборка улица + город:
select S.ID s_id, S.NAME s_name, C.NAME c_name from STREET S
join CITY C on C.ID = S.CITY_ID
155 000 записей в выборке.
---
Программка на Delphi. VST, FIB+ (заменишь на ibx сам, у меня таких бананов нет).
В константах указана строка коннекта с базой и путь к клиентской библиотеке, заменишь на свои:
const
// Строка коннекта
c_dbn = '127.0.0.1/3100:D:/Trash/tstVST/streets.fdb';
// Путь к библиотеке fbclient.dll
c_lbn = 'D:/Program Design/Delphi2007/EstExe/bcSupport/fbClient/fbclient.dll';
В vst дереве - два столбца: название улицы [0] и название города [1].
Инициализация дерева: с помощью qSelectIds (TpFIBQuery) заливаем все идентификаторы улиц в массив
Код:
procedure TForm1.LoadIds;
var
i: Integer;
begin
qSelectIds.ExecQuery;
SetLength(fIds, 10000);
i := 0;
while not qSelectIds.Eof do
begin
if i = Length(fIds) then
SetLength(fIds, Length(fIds) + 10000);
fIds[i] := qSelectIds.Fields[0].AsInteger;
Inc(i);
qSelectIds.Next;
end;
SetLength(fIds, i);
end;
- можно ускорить, если очень захочется, разными способами, хоть в отдельной нити или выбирать одним блоком/блобом и т.д. и т.п.
Сообщаем дереву, сколько у нас записей:
vstMain.RootNodeCount := Length(fIds);
Всё. В событии OnGetText дерево запрашивает, что показывать.
Выбираем значения полей в qSelectAll (TpFIBQuery)
select S.NAME, C.NAME
from STREET S
join CITY C on C.ID = S.CITY_ID
where S.ID = :ID
Код (без кэширования):
procedure TForm1.vstMainGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
begin
if not Assigned(Node) then Exit;
if not (Column in [0, 1]) then Exit;
if qSelectAll.Params[0].AsInteger <> fIds[Node.Index] then
begin
qSelectAll.Params[0].AsInteger := fIds[Node.Index];
qSelectAll.ExecQuery;
end;
CellText := qSelectAll.Fields[Column].AsString;
end;
Дабы не травмировать тонкие струны, перед обращением к qSelectAll лезем в кэш который, ты пишешь сам. Например, используя разреженные массивы или словари из https://github.com/fundamentalslib/fundamentals5
-
Вложение: tstVST.7z
(Размер: 284.98KB, Загружено 352 раза)
-
Вложение: Безымянный.png
(Размер: 16.86KB, Загружено 1333 раза)
[Обновления: Wed, 01 February 2023 18:15] Известить модератора
|
|
|
|
|
Re: IBX: буферизация записей [сообщение #1533 является ответом на сообщение #1531] |
Thu, 02 February 2023 00:47 |
Сообщений: 197 Зарегистрирован: September 2022
|
Senior Member |
|
|
Док писал(а) Wed, 01 February 2023 21:58Т.е. ты на отображение каждого узла вызываешь ExecQuery?
Какой-то чат-ГПТ без обратной связи, честное слово. Я тебе про принципы работы с vst, а ты на какую-то фигню смотришь.
Вообще-то, в приведенном коде запрос может быть отправлен даже не для каждого узла, а для каждого поля и вообще сдуру можно и член сломать.
Про кэш я уже три раза писал. И - запрос может быть не для каждого узла, а для набора отображаемых в данный момент узлов (тех, которых нет в кэше, конечно) - включи фантазию. Я вот тестировал - при включенном кэше не ощутил разницы, по одной записи тянуть, или по 40 штук за раз (если запросы препарированные), именно для данной задачи. Прикинь, даже без кэша нормально, если не совсем тухлая локалка и юзеров всего пара десятков, но что мешает добавить кэш?
|
|
|
|
|
Re: IBX: буферизация записей [сообщение #1538 является ответом на сообщение #1533] |
Thu, 02 February 2023 13:40 |
|
Док
Сообщений: 101 Зарегистрирован: June 2022
|
Senior Member |
|
|
МорскойДесант писал(а) Thu, 02 February 2023 00:47Док писал(а) Wed, 01 February 2023 21:58Т.е. ты на отображение каждого узла вызываешь ExecQuery?
Какой-то чат-ГПТ без обратной связи, честное слово. Я тебе про принципы работы с vst, а ты на какую-то фигню смотришь.
Вообще-то, это должны быть мои слова
Я выложил готовый проект, где данные только отображаются деревом (из датасета, как и предложил ПВП), и приложил гифку на 15 сек (которую, похоже, ты не досмотрел до конца), где первые 1000 записей фетчатся/отображаются в основном потоке, а оставшиеся почти 1 000 000 записей фетчатся/отображаются в доп.потоке. Но ты не вник
Ладно, в любом случае, спасибо тебе за участие и идеи. Я и правда не знал, что VTV может просто отображать записи без хранения
FPC/Lazarus (trunk) | Win10 x64 Ultim/Debian 11 amd64/Darwin x86_64 Monterey | Firebird 3.0.10 x64 | IBX by TonyWhyman
https://zoltanleo.blogspot.com/
[Обновления: Thu, 02 February 2023 13:43] Известить модератора
|
|
|
|
|
|
|
Re: IBX: буферизация записей [сообщение #1564 является ответом на сообщение #1501] |
Mon, 06 February 2023 12:24 |
pastor
Сообщений: 81 Зарегистрирован: June 2022 Географическое положение: Калуга
|
Member |
|
|
Док писал(а) Sat, 28 January 2023 18:56
1. искать записи по меморидатасету проще, чем писать функции поиска по VTV - посмотрю
2. тогда при скроле придется отслеживать, достигли ли мы последний(нижний) узел дерева, и фетчить записи, начиная с определенного ID. А если ранее загруженные записи были изменены, то в целом данные в дереве уже будут не актуальны. Проще обновлять мемдатасет и грузить актуальные записи. К тому же, для экспериментов я беру самые экстремальные условия: без фильтрации, огромное кол-во записей - в реальности вряд ли такое встретится
и поиск быстрый и фильтр тоже быстрый.
|
|
|
Переход к форуму:
Текущее время: Thu Nov 21 22:17:21 GMT+3 2024
Общее время, затраченное на создание страницы: 0.01065 секунд
|