Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi SQL Server : Perfomanceprobleme - sinnvolle DB Verbindung gesucht (https://www.delphipraxis.net/158620-sql-server-perfomanceprobleme-sinnvolle-db-verbindung-gesucht.html)

Piro 24. Feb 2011 09:53

Datenbank: MS SQL 2005 • Version: Express • Zugriff über: ADO

SQL Server : Perfomanceprobleme - sinnvolle DB Verbindung gesucht
 
Moin zusammen,

mich würde mal interessieren, wie Ihr eure Anwendung in Bezug auf die SQL Verbingung programmiert bzw. einstellt.

Zitat:

Mein SQL Server: 2 CPU's 2.66GHz mit 2GB RAM
Ich habe seit ein paar Tagen Performanceprobleme mit meinem SQL 2005 Express Server.

Morgens, wenn die Anwender sich am Computer anmelden, wird mein Programm ausgeführt, welches Computerinformationen über WMI ermittelt und in die SQL DB schreibt. Das Programm braucht normalerweise nicht länger als 30 Sekunden, um die Daten zu ermitteln und in die DB zu schreiben.

Es kann vorkommen, dass 500 Anwender gleichzeit Daten in die DB schreiben. In dieser Zeit ist der SQL Server an seinem Limit und hat längere bis ganz lange Antwortzeiten. Wenn die Stoßzeit des Anmeldens vorbei ist, ist er wieder performat.

SQL Einstellungen im Programm:
Code:
KeppConnecton: True
Datenübermittlung via TADODataSet
Sollte man eventuell auf TADOCommand umsteigen und mit Parameter arbeiten und ggf. prepare verwenden? Massendaten sind es aber eigentlich nicht. Wäre schön zu wissen, wie ihr das händeln würdet bzw. was ich noch optimieren könnte.

Des weiteren habe ich Programme, die die Informationen anzeigen für eine handvoll Anwender. Würdet ihr die SQL Verbindung immer wieder trennen nach einer DB Abfrage oder einmal öffnen und KeppConnection True lassen und erst mit dem Programmende die Verbindung schließen?

Ich habe das Gefühl, dass er die Resourcen nicht frei gibt, wenn ich die Verbindung mit SQLConnection.Close beendet im Programm. Erst wenn das ganz Programm geschlossen wird.

Wäre schön zu wissen, wie Ihr solche Anforderungen löst?

Vielen Dank im voraus und hoffe auf Eure Erfahrungen.

Sven

taveuni 24. Feb 2011 10:25

AW: SQL Server : Perfomanceprobleme - sinnvolle DB Verbindung gesucht
 
Zitat:

Zitat von Piro (Beitrag 1084010)
Es kann vorkommen, dass 500 Anwender gleichzeit Daten in die DB schreiben. In dieser Zeit ist der SQL Server an seinem Limit und hat längere bis ganz lange Antwortzeiten. Wenn die Stoßzeit des Anmeldens vorbei ist, ist er wieder performat.

Ist dann wohl wirklich ein SQL Server Performance Problem.
2005 Express ist auf eine CPU und 1GB Ram beschränkt.
Kann es sein dass dein Applikationsdesign suboptimal ist?
Bei einer Client-Server Anwendung könnte man die Daten z.b. cachen und dann gesammelt inserten.

Wie werden denn die Daten geschrieben (einzelne Inserts via Schleife, Transaktionen ..)?

Zitat:

Zitat von Piro (Beitrag 1084010)
Das Programm braucht normalerweise nicht länger als 30 Sekunden, um die Daten zu ermitteln und in die DB zu schreiben.

Wo wird "normalerweise" die Zeit gebraucht? Um die Daten zu ermitteln oder um diese in die Datenbank zu schreiben?

jobo 24. Feb 2011 10:38

AW: SQL Server : Perfomanceprobleme - sinnvolle DB Verbindung gesucht
 
Ich hab schon lange nicht mehr mit SQL Server gearbeitet. Aus der ganzen ADO.Net Technik, Verbindungstrennung, lokale Datenhaltung, etc. pp. habe ich immer abgeleitet, dass es "best practice" ist, sprich MS das extra so designed hat, um seine Server zu schonen.

2 Gedanken unabhängig vom Server:
- WMI auszulesen könnte teilweise auch was hakelig sein, daher erst auslesen und komplett sammeln, im nächsten Schritt an den Server senden (falls es nicht schon so ist)
- Wie schreibst Du in die SQL DB? Mittels Dataset.insert, fieldbyname('field').value := xy … ?
Das wäre wahrscheinlich die ungünstigste Lösung. Geeigneter wäre einzelne, parametrierte Inserts via TADOQuery oder vielleicht auch komplette Batch Scripte, wenn es viele inserts sind.
Da weiß ich leider nicht, ob MS SQL via ADOQuery soetwas schluckt. (Vielleicht reicht es, einzelne Statements per ; zu trennen)

EarlyBird 24. Feb 2011 10:53

AW: SQL Server : Perfomanceprobleme - sinnvolle DB Verbindung gesucht
 
wenn es um schnellen Datentransfer auf den SQL-Server geht kann ich dir die TMSLoader Komponente von Devart empfehlen.
(ist in den "SDAC Professional Edition components" enthalten)
Damit habe ich sehr gute Erfahrungen gemacht.
Für mich hat sich die Investition gelohnt.

Bummi 24. Feb 2011 10:54

AW: SQL Server : Perfomanceprobleme - sinnvolle DB Verbindung gesucht
 
bei SQL-Express, Vorschlag
wenn der Umfang es erlaubt eine Prozedur schreiben die alle Parameter "schluckt", nachdem diese gesammelt wurden und die Connection nur so lange wie nötig offen halten

Bernhard Geyer 24. Feb 2011 13:26

AW: SQL Server : Perfomanceprobleme - sinnvolle DB Verbindung gesucht
 
Wo genau hängt das Programm? Wie schreibst du die Daten in die DB? ich hoffe doch direkt mit parametrisierten "INSERT..."-Anweisungen bzw. SP's. Oder öffnenst du eine TADOTable und lässts erst mal die gesammte DB-Tabelle zum Client übertragen?

Piro 24. Feb 2011 13:57

AW: SQL Server : Perfomanceprobleme - sinnvolle DB Verbindung gesucht
 
Also ich mach das so:

Ablauf:
1. WMI Daten in Records bzw. Arrays speichern (findet im Program lokal statt)
2. Records bzw. Arrays in die DB (jeweilige Tabelle) speichern
3. Programm beenden

Folgende Daten werden übertragen, die in der dazugehörigen SQL Tabelle sind:
1. Allgemeine Informationen
2. Arbeitsspeicher
3. Festplatten
4. Netzwerklaufwerke
5. Netzwerkinfos
6. Software
7. Hotfixes
8. Printer
9. Monitors

Folgende Komponenten verwende ich:
- TADOConnection
- TADODataSet
- TADOCommand (nur für das Löschen)

Folgende Prozeduren verwende ich:
z.B.: Allgemeine Infos
Delphi-Quellcode:
   DSData.Close;
   DSData.CommandText := 'Select id from computer where (computername='+QuotedStr(sysname)+') and (serial='+QuotedStr(serial)+')';
   DSData.Open;
   id := DSData.FieldByName('id').AsString;
   DSData.Close;

   if id <> '' then
   begin
     DSData.Close;
     DSData.CommandText := 'Select * from computer where id='+id;
     DSData.Open;
     DSData.Edit;
   end
   else
   begin
     DSData.Close;
     DSData.CommandText := 'Select * from computer';
     DSData.Open;
     DSData.Append;
   end;

   try
     DSData.FieldByName('computername').AsString    := sysname;
     DSData.FieldByName('domain').AsString          := BasicInfo.domain;
     DSData.FieldByName('manufacturer').AsString    := BasicInfo.manufacturer;
     DSData.FieldByName('model').AsString           := BasicInfo.model;
     DSData.FieldByName('serial').AsString          := BasicInfo.serial;
     DSData.FieldByName('assetclass').AsInteger     := BasicInfo.assetclass;
     ...
     DSData.POST;
Für die weiteren Bereich ist es immer die gleiche Procedure, nur die Daten und die Tabelle ändert sich.
Delphi-Quellcode:
for i := 0 to max_AMemory do
begin
  if AMemory[i].name = '' then
    break;

  DSData.Close;
  DSData.CommandText := 'Select * from computer_memory where sid = ' + id + ' and name = '+QuotedStr(AMemory[i].name);
  DSData.Open;

  if DSData.RecordCount > 0 then
    DSData.Edit
  else
    DSData.Append;

  DSData.FieldByName('name').AsString      := AMemory[i].name;
  DSData.FieldByName('capacity').AsString  := AMemory[i].capacity;
  DSData.FieldByName('speed').AsString     := AMemory[i].speed;
  DSData.FieldByName('lastupdate').AsString := FormatDateTime('dd.mm.yyyy hh:nn:ss',lastupdate);
  DSData.FieldByName('sid').AsString       := id;
  DSData.Post;
end;

// Alte Einträge löschen
SQLCommand.CommandText := 'delete from computer_memory where sid = ' + QuotedStr(id) + ' and lastupdate <> ' + QuotedStr(FormatDateTime('dd.mm.yyyy hh:nn:ss',lastupdate));
SQLCommand.Execute;
Zitat:

parametrisierten "INSERT..."-Anweisungen bzw. SP's
Habe ich damit wirklich einen Performancegewinn? Ich verwende das nur bei Massendaten. Da klappt es super aber ist, dass das gleiche, wenn ich immer wieder eine andere Tabelle anwählen muss. Dann brauche ich 8 x TADOCommand, oder?
Was sind SP's?

Leider kann ich nicht nur "EINEN" parametrisierten INSERT benutzen, da ich mehre Tabellen verwende. Das wäre echt gut. Aber naja. Es muss ja auch anders gehen.

Gruß, Sven

Sir Rufo 24. Feb 2011 13:57

AW: SQL Server : Perfomanceprobleme - sinnvolle DB Verbindung gesucht
 
Bei der Anzahl von Clients würde ich die nicht direkt auf den SQL-Server loslassen (schon weil der ja ganz klein ist).

Einfache Lösung (mit Hausmitteln zu erledigen):

FTP-Server einschalten und die Clients übertragen ihre Daten an den FTP-Server.
Ein kleiner Dienst überwacht den Ordner und pustet diese Daten dann in den SQL-Server rein.

Vorteile:
- Über den Dienst steuerst du die Auslastung des Servers (evtl. nur x Einträge pro Sekunde reinpusten)
- Nur eine Stelle (der Dienst) überträgt die Daten an den SQL-Server, Änderungen am DB-Layout sind somit ohne weiteres möglich
- Dienst abschalten und den SQL-Server warten/sichern - Die Clients werden trotzdem nicht beim Abladen gestört

Ach ja, so wie du das im Moment machst (Append, Post) ist zudem auch die langsamste aller Methoden.

Piro 24. Feb 2011 14:50

AW: SQL Server : Perfomanceprobleme - sinnvolle DB Verbindung gesucht
 
Coole Idee mit dem FTP Server & dem Dienst. Da denke ich mal mehr drauf rum.

Was wäre denn die beste Lösung ohne Append, Post? Parametrisierte INSERTs für die 8 Bereiche. Würde es gerne vorher einmal wissen bevor ich mir die Mühe mache, mein Programm anzupassen.

Sir Rufo 24. Feb 2011 14:56

AW: SQL Server : Perfomanceprobleme - sinnvolle DB Verbindung gesucht
 
Zitat:

Zitat von Piro (Beitrag 1084137)
Parametrisierte INSERTs für die 8 Bereiche. Würde es gerne vorher einmal wissen bevor ich mir die Mühe mache, mein Programm anzupassen.

Ja ;)

Das geht aber auch in einem Rutsch:
Code:
INSERT INTO Tabelle1 ( fooa, foob ) VALUES ( :fooa, :foob );
INSERT INTO Tabelle2 ( fooc, food ) VALUES ( :fooc, :food );
...
Somit benötigst du nur 1 Query, wo du bislang mehrere hast

Ach ja ... wenn du Parameter öfter verwenden möchtest, dann so
Code:
SET @fooa = :fooa;
SET @foob = :foob;
SET @fooc = :fooc;
INSERT INTO Tabelle1 ( fooa, foob ) VALUES ( @fooa, @foob );
INSERT INTO Tabelle2 ( fooa, fooc ) VALUES ( @fooa, @fooc );
...
Und wenn man sich ganz oft wiederholt (z.B. die Liste der installierten Software) und die Tabelle so aussieht:
Code:
Domain
Computer
IP-Adresse
Software
dann macht es durchaus Sinn, nur die Spalte Software in eine temp. Tabelle auf den SQL-Server zu schieben und die dann an die Ziel-Tabelle anzuhängen.
Code:
INSERT INTO Software (Domain, Computer, IP, Software )
SELECT :Domain, :Computer, :IP, Software
FROM tempSoftware
Das spart enorm Bandbreite, weil die Informationen zu Domain, Computer, IP-Adresse nur einmal übertragen werden und nicht x-mal


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:24 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz