![]() |
VST mit ca. 50.000 Datensätze verdammt langsam, warum???
Guten Abend,
ich verwende ein VST, um Daten aus einer MS SQL Express 2005 anzuzeigen. Es kann vorkommen, dass das VST um die 50.000 Datensätze erhält. Wenn die Daten ins VST geschrieben werden, dauert es unwahrscheinlich lange (gefühlte 2 Minuten). Die Daten werden in eine Klasse gespeichert, so wie es im Video-Tutorial vom Stammtisch zu sehen ist. Folgendes mache ich mit dem VST: - Haederleiste bekommt einen Hintergrund - GetText, um die Daten anzuzeigen - GetImageIndex - CompareNode Das ist eigentlich alles. Wenn ich GetText und CompareNode herausnehme. Geht es etwas schneller aber noch nicht schnell genug. Kann es sein, dass ein VST für solche Datenmengen nicht gemacht ist, weil das VST dann zuviel machen muss und somit langsam wird? Vielen Dank im voraus. Sven |
Re: VST mit ca. 50.000 Datensätze verdammt langsam, warum???
Die Frage ist auch, ob es sinnvoll ist 50 000 Einträge anzuzeigen
|
Re: VST mit ca. 50.000 Datensätze verdammt langsam, warum???
Wie füllst du denn den VST? Per InitNode oder per AddNode?
Nutzt du BeginUpdate und EndUpdate? Meines Wissens stellen 50.000 Einträge kein Problem dar. Frage ist auch, welche Daten die in dem Data Record des jeweiligen Nodes hinterlegst. |
Re: VST mit ca. 50.000 Datensätze verdammt langsam, warum???
das befüllen sollte schnell gehen, wenn du vst.beginupdate und endupdate verwendest, da der vst nur speicher für den zeiger (und natürlich die Nodestruktur) belegen wird.
vermutlich dauert das umkopieren aus der db so lange. du könntest, wenn du die anzahl der daten kennst, den nodecount setzen und im oninitnode die zeiger setzen. das geht dann einen tick schneller. |
Re: VST mit ca. 50.000 Datensätze verdammt langsam, warum???
Hallo,
ich würde erst mal ein paar Breakpoints setzen, um festzustellen, wo er hängt, und dann mit 1/2-Einträgen testen, ob der VST zu viel "unternimmt". Heiko |
Re: VST mit ca. 50.000 Datensätze verdammt langsam, warum???
Das Programm ist eine Art Verwaltung von Subnetzen mit den jeweilige Wertenbereichen.
Hier meine Datenstruktur:
Delphi-Quellcode:
So lade ich die Daten aus der DB in das VST
type
TOSubnetDetailsData = class private // public id : String; ipaddress : String; device : String; dhcp_exclude : Integer; dhcp_mac : String; site : String; building : String; floor : String; position : String; vlan : String; subnetdevice : String; description : String; sid : String; function GetDHCP_ExcludedName: String; property dhcp_excludedname : String read GetDHCP_ExcludedName; end;
Delphi-Quellcode:
Die Abfrage gegen die Datenbank geht schnell und das AddChild dauert seine Zeit. Kann ich da noch etwas optimieren?
procedure Tfrm_main.SQLDataToVST_SubnetDetails;
var i : Integer; SubnetDetailsData : TOSubnetDetailsData; begin vst_network_subnetdetails.Clear; DSData.Close; DSData.CommandText := 'select network_subnetdetails.id,'+ 'network_subnetdetails.ipaddress,'+ 'network_subnetdetails.device,'+ 'network_subnetdetails.dhcp_exclude,'+ 'network_subnetdetails.dhcp_mac,'+ 'network_sites.site,'+ 'network_subnets.building,'+ 'network_subnets.floor,'+ 'network_subnets.position,'+ 'network_subnets.vlan,'+ 'network_subnets.device as subnetdevice,'+ 'network_subnetdetails.description,'+ 'network_subnetdetails.subnet_id '+ 'from network_subnets '+ 'inner join network_subnetdetails on network_subnets.id = network_subnetdetails.subnet_id '+ 'inner join network_sites on network_subnets.site_id = network_sites.id '+ 'order by cast(parsename([ipaddress], 4) as int),'+ 'cast(parsename([ipaddress], 3) as int),'+ 'cast(parsename([ipaddress], 2) as int),'+ 'cast(parsename([ipaddress], 1) as int)'; DSData.Open; DSData.First; for i := 0 to DSData.RecordCount - 1 do begin SubnetDetailsData := TOSubnetDetailsData.Create; with SubnetDetailsData do begin id := DSData.FieldByName('id').AsString; ipaddress := DSData.FieldByName('ipaddress').AsString; device := DSData.FieldByName('device').AsString; dhcp_exclude := DSData.FieldByName('dhcp_exclude').AsInteger; dhcp_mac := DSData.FieldByName('dhcp_mac').AsString; site := DSData.FieldByName('site').AsString; building := DSData.FieldByName('building').AsString; floor := DSData.FieldByName('floor').AsString; position := DSData.FieldByName('position').AsString; vlan := DSData.FieldByName('vlan').AsString; subnetdevice := DSData.FieldByName('subnetdevice').AsString; description := DSData.FieldByName('description').AsString; sid := DSData.FieldByName('subnet_id').AsString; end; vst_network_subnetdetails.AddChild(nil, SubnetDetailsData); Application.ProcessMessages; DSData.Next; end; DSData.Close; end; Die Struktur und die Methoden sind in Anlehnung an das Stammtisch-Video für VST. Falls das ein normales Verhalten des VST ist, werde ich den View limitieren. Sven |
Re: VST mit ca. 50.000 Datensätze verdammt langsam, warum???
Fehlt das BeginUpdate/EndUpdate in der Prozedur, oder ist das irgendwo anders?
Mein Tree ist mit 27.000 Nodes auch blitzschnell, ich denke nicht, dass es am Tree liegt. HTH |
Re: VST mit ca. 50.000 Datensätze verdammt langsam, warum???
Im GetText sollte eigentlich der Text geladen werden, nicht vorher.
Wenn du 50.000 Datensätze hast und 12 strings pro record - da möchte ich mal den Speicherverbauch sehen. Auch sehe ich kein BeginUpdate und kein EndUpdate. Normalerweise sollte man einfach per VST.RootNodeCount := DataSet.RecordCount die Anzahl der Nodes festlegen und im InitNode die RecordNo setzen und dann im GetText die Daten zu der RecordID auslesen. |
Re: VST mit ca. 50.000 Datensätze verdammt langsam, warum???
In dem Videotutorial gab es kein BeginUpdate und EndUpdate. Wozu ist das relevant?
Delphi-Quellcode:
procedure Tfrm_main.FormCreate(Sender: TObject);
begin ... // Initialisierung - Speichergröße des Node bekanntgeben sonst Exceptions vst_network_subnetdetails.NodeDataSize := sizeof(TOSubnetDetailsData); .. Hier meine Methoden für das VST:
Delphi-Quellcode:
Und was sagts jetzt dazu?
procedure Tfrm_main.vst_network_subnetdetailsAdvancedHeaderDraw(
Sender: TVTHeader; var PaintInfo: THeaderPaintInfo; const Elements: THeaderPaintElements); begin if hpeBackground in Elements then begin PaintInfo.TargetCanvas.Brush.Bitmap := img_bg_20.Picture.Bitmap; if PaintInfo.Column <> nil then DrawFrameControl(PaintInfo.TargetCanvas.Handle, PaintInfo.PaintRectangle,DFC_BUTTON,DFCS_FLAT or DFCS_ADJUSTRECT); PaintInfo.TargetCanvas.FillRect(PaintInfo.PaintRectangle); end; end; procedure Tfrm_main.vst_network_subnetdetailsAfterItemErase( Sender: TBaseVirtualTree; TargetCanvas: TCanvas; Node: PVirtualNode; ItemRect: TRect); begin if Sender.Selected[Node] then Exit; if Odd(Node.Index) then TargetCanvas.Brush.Color := $F8F8F8 else TargetCanvas.Brush.Color := clWhite; TargetCanvas.FillRect(ItemRect); end; procedure Tfrm_main.vst_network_subnetdetailsBeforeCellPaint( Sender: TBaseVirtualTree; TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex; CellPaintMode: TVTCellPaintMode; CellRect: TRect; var ContentRect: TRect); var SubnetDetailsData : TOSubnetDetailsData; begin // Spalte 0 einfärben, wenn es sich um ein Exclude handelt SubnetDetailsData := TOSubnetDetailsData(vst_network_subnetdetails.GetNodeData(Node)^); if vst_network_subnetdetails.Header.Columns[Column].Text = '' then begin if SubnetDetailsData.dhcp_exclude = 0 then begin TargetCanvas.Brush.Color := $D1D1D1; TargetCanvas.FillRect(CellRect); end; end; end; procedure Tfrm_main.vst_network_subnetdetailsCompareNodes( Sender: TBaseVirtualTree; Node1, Node2: PVirtualNode; Column: TColumnIndex; var Result: Integer); var SubnetDetailsData1 : TOSubnetDetailsData; SubnetDetailsData2 : TOSubnetDetailsData; begin SubnetDetailsData1 := TOSubnetDetailsData(vst_network_subnetdetails.GetNodeData(Node1)^); SubnetDetailsData2 := TOSubnetDetailsData(vst_network_subnetdetails.GetNodeData(Node2)^); if column > -1 then begin if vst_network_subnetdetails.Header.Columns[Column].Text = 'Device' then Result := CompareStr(SubnetDetailsData1.device, SubnetDetailsData2.device); if vst_network_subnetdetails.Header.Columns[Column].Text = 'DHCP' then Result := CompareStr(SubnetDetailsData1.dhcp_excludedname, SubnetDetailsData2.dhcp_excludedname); if vst_network_subnetdetails.Header.Columns[Column].Text = 'DHCP MAC' then Result := CompareStr(SubnetDetailsData1.dhcp_mac, SubnetDetailsData2.dhcp_mac); if vst_network_subnetdetails.Header.Columns[Column].Text = 'Site' then Result := CompareStr(SubnetDetailsData1.site, SubnetDetailsData2.site); if vst_network_subnetdetails.Header.Columns[Column].Text = 'Building' then Result := CompareStr(SubnetDetailsData1.building, SubnetDetailsData2.building); if vst_network_subnetdetails.Header.Columns[Column].Text = 'Floor' then Result := CompareStr(SubnetDetailsData1.floor, SubnetDetailsData2.floor); if vst_network_subnetdetails.Header.Columns[Column].Text = 'Position' then Result := CompareStr(SubnetDetailsData1.position, SubnetDetailsData2.position); if vst_network_subnetdetails.Header.Columns[Column].Text = 'VLAN' then Result := CompareStr(SubnetDetailsData1.vlan, SubnetDetailsData2.vlan); if vst_network_subnetdetails.Header.Columns[Column].Text = 'Subnet Device' then Result := CompareStr(SubnetDetailsData1.subnetdevice, SubnetDetailsData2.subnetdevice); if vst_network_subnetdetails.Header.Columns[Column].Text = 'Description' then Result := CompareStr(SubnetDetailsData1.description, SubnetDetailsData2.description); end; end; procedure Tfrm_main.vst_network_subnetdetailsFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode); var SubnetDetailsData : TOSubnetDetailsData; begin SubnetDetailsData := TOSubnetDetailsData(vst_network_subnetdetails.GetNodeData(Node)^); SubnetDetailsData.Free; end; procedure Tfrm_main.vst_network_subnetdetailsGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString); var SubnetDetailsData : TOSubnetDetailsData; begin SubnetDetailsData := TOSubnetDetailsData(vst_network_subnetdetails.GetNodeData(Node)^); if vst_network_subnetdetails.Header.Columns[Column].Text = 'IP Address' then CellText := SubnetDetailsData.ipaddress; if vst_network_subnetdetails.Header.Columns[Column].Text = 'Device' then CellText := SubnetDetailsData.device; if vst_network_subnetdetails.Header.Columns[Column].Text = 'DHCP' then CellText := SubnetDetailsData.dhcp_excludedname; if vst_network_subnetdetails.Header.Columns[Column].Text = 'DHCP MAC' then CellText := SubnetDetailsData.dhcp_mac; if vst_network_subnetdetails.Header.Columns[Column].Text = 'Site' then CellText := SubnetDetailsData.site; if vst_network_subnetdetails.Header.Columns[Column].Text = 'Building' then CellText := SubnetDetailsData.building; if vst_network_subnetdetails.Header.Columns[Column].Text = 'Floor' then CellText := SubnetDetailsData.floor; if vst_network_subnetdetails.Header.Columns[Column].Text = 'Position' then CellText := SubnetDetailsData.position; if vst_network_subnetdetails.Header.Columns[Column].Text = 'VLAN' then CellText := SubnetDetailsData.vlan; if vst_network_subnetdetails.Header.Columns[Column].Text = 'Subnet Device' then CellText := SubnetDetailsData.subnetdevice; if vst_network_subnetdetails.Header.Columns[Column].Text = 'Description' then CellText := SubnetDetailsData.description; end; procedure Tfrm_main.vst_network_subnetdetailsHeaderClick(Sender: TVTHeader; Column: TColumnIndex; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if Button = mbLeft then begin if Column = vst_network_subnetdetails.Header.SortColumn then vst_network_subnetdetails.Header.SortDirection := TSortDirection(1-ord(vst_network_subnetdetails.Header.SortDirection)) else vst_network_subnetdetails.Header.SortColumn := Column; end; end; procedure Tfrm_main.vst_network_subnetdetailsHeaderDrawQueryElements( Sender: TVTHeader; var PaintInfo: THeaderPaintInfo; var Elements: THeaderPaintElements); begin // Erforderlich für das Headerausehen Elements := [hpeBackground]; end; |
Re: VST mit ca. 50.000 Datensätze verdammt langsam, warum???
Hast du es wenigstens mal mit Begin/EndUpdate versucht? Das würde dann so aussehen...
Delphi-Quellcode:
Ansonsten: Kommentier nach und nach deinen Code in den Ereignissen des VT aus und arbeite dich langsam vor. Dann sollte sich das Problem schnell zeigen...
DSData.Open;
DSData.First; vst_network_subnetdetails.BeginUpdate; // Neu vst_network_subnetdetails.Clear; // Neu for i := 0 to DSData.RecordCount - 1 do begin SubnetDetailsData := TOSubnetDetailsData.Create; with SubnetDetailsData do begin id := DSData.FieldByName('id').AsString; ipaddress := DSData.FieldByName('ipaddress').AsString; device := DSData.FieldByName('device').AsString; dhcp_exclude := DSData.FieldByName('dhcp_exclude').AsInteger; dhcp_mac := DSData.FieldByName('dhcp_mac').AsString; site := DSData.FieldByName('site').AsString; building := DSData.FieldByName('building').AsString; floor := DSData.FieldByName('floor').AsString; position := DSData.FieldByName('position').AsString; vlan := DSData.FieldByName('vlan').AsString; subnetdevice := DSData.FieldByName('subnetdevice').AsString; description := DSData.FieldByName('description').AsString; sid := DSData.FieldByName('subnet_id').AsString; end; vst_network_subnetdetails.AddChild(nil, SubnetDetailsData); Application.ProcessMessages; DSData.Next; end; vst_network_subnetdetails.EndUpdate; // Neu DSData.Close; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:14 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz