AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Delphi TAdoTable.Open() sprengt Arbeitsspeicherlimit
Thema durchsuchen
Ansicht
Themen-Optionen

TAdoTable.Open() sprengt Arbeitsspeicherlimit

Ein Thema von AxelO · begonnen am 7. Okt 2024 · letzter Beitrag vom 22. Okt 2024
Antwort Antwort
Seite 2 von 2     12   
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.071 Beiträge
 
Delphi 12 Athens
 
#11

AW: TAdoTable.Open() sprengt Arbeitsspeicherlimit

  Alt 8. Okt 2024, 16:02
Die Query kann auch .Edit und .Append?
Natürlich ... so lange das SELECT der Query ein Rückschreiben erlaubt.
Notfalls kann man aber auch eigene INSERT/EDIT/DELETE-Statements angeben, wenn es gewisse Sonderfälle erfordern.

Eine Query mit SELECT * FROM deinetablle entspricht der Table.
Lädt also auch ALLES.

Teilweise kann man aber auch ein Nachladen/Paging aktieren (wenn DBMS, Treiber und QueryKomponente es ermöglichen)
Dann wird nicht sofort alles geladen, sondern erst nach und nach, während man mit Next durchläuft,
bzw. es wird immer nur ein kleiner Ausschnitt (Page) geladen und dann die Nächste und wieder freigeben.
z.B. bei Grids muß natürlich auch das Grid und sein DataControler es unterstützen, wenn man quasi nur den grade sichbaren Bereich geladen haben will.

Bei der Query kann man aber noch die Felder/Spalten auswählen/einschränken
und vor allem auch die Records/Zeilen, durch ein entsprechendes WHERE und/oder LIMIT.
Außerdem kann man JOINs einbinden und vieles mehr.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.490 Beiträge
 
Delphi 7 Professional
 
#12

AW: TAdoTable.Open() sprengt Arbeitsspeicherlimit

  Alt 8. Okt 2024, 17:17
Statt TADOTable TADOQuery nehmen. Scheint sich (zuweilen) etwas dynamischer zu verhalten.
Aha, interessant. Also die ADOTable einfach durch eine ADOQuery mit Abfrage "Select * from..." ersetzen, das ist dann gleichwertig? Die Query kann auch .Edit und .Append?
Ja, bei einem Select * from tabelle where irgendeinebedingung geht das problemlos. Bei Joins über mehrere Tabellen geht's nicht. Da TAdoQuery nur eine Tabelle kann, kannst Du das durch eine TADOQuery (mit 'nem entsprechenden Select) ersetzen.
Benötigst Du tatsächlich alle Daten der Tabelle immer an "einem Stück"?
Denke schon, da in einem Zuge auf a) Vorhandensein und b) Gleichheit der jeweiligen Quelltabellen-Zeile in der Zieltabelle geprüft und dann ggfs. die Zeile entweder eingefügt oder aktualisiert wird. Dazu muss der Vergleich ja immer die Zieltabelle als Ganzes sehen, oder?
Das kann man aber auch anders lösen. Tabelle A in sinnvollen Teilmengen laden (Query mit passender Wherebedingung) und satzweise durchgehen. Genau diesen einen Satz per weiterer Query in der Tabelle B suchen. Prüfen, einfügen und aktuallisieren dieses Satzes wie bisher.
Was genau wird gemacht? Tabelle lesen und woanders schreiben?
Mehrere Tabellen aus einer Quell-Datenbank werden mit den entsprechenden Tabellen in einer Ziel-Datenbank abgeglichen. Wenn die Quellzeile in der Zieltabelle nicht vorhanden ist, wird sie eingefügt, ansonsten aktualisiert. Es wird in der Zieltabelle aber nicht gelöscht, also es ist keine vollständige "Synchronisation". Zur Ermittlung der Gleichheit zweier Zeilen dient (wo vorhanden) eine proprietäre UID, ansonsten inhaltlicher Vergleich aller Spalten. Das Einfügen bzw. Aktualisieren erfolgt aber nicht mit SQL-Insert- oder SQL-Update-Befehlen, sondern über die API mit .Append bzw. .Edit. (Geht Append/Edit überhaupt mit einer Query?)
Das sollte mit oben beschriebenen Vorgehen realisierbar sein.
Was ich mir noch an Alternativen überlegt habe, um um das .Open() herumzukommen:

- Aus den Access-DBs auf den SQL Server nicht direkt in die riesigen Originaltabellen kopieren, sondern erstmal in leere Dummy-Zieltabellen mit derselben Struktur, denn dann geht das .Open() ja schnell. Dann ein SQL-MERGE-Kommando absetzen, das jeweils die Dummytabelle in die Originaltabelle ein"merged" (oder Kombination aus INSERT und UPDATE). Dann ist ADO außen vor und der Server macht die Arbeit selbst. Allerdings müsste ich dann die Identitätsprüfung der Zeilen in SQL selbst formulieren, das dürfte auch haarig werden.
- Ginge sowas auch mit Stored Procedures? Nur eine vage Idee.
Ja. Meine Devise war eigentlich immer: Was die Datenbank machen kann, lass die Datenbank machen, dafür ist sie da. Alles (über das Netzwerk) in den eigenen Arbeitspeicher holen, mit eigenem Programm verarbeiten und dann die Datenbank schreibenlassen, ist umständlich und aufwändig und niemals schneller als die Datenbank (auch wenn der Programmieraufwand in Delphi geringer erscheint).
Wenn die Daten nicht an einem Stück benötigt werden, sondern das Kopieren von A nach B auch in mehreren Schritten hintereinander (durchaus in einer Transaktion) erfolgen kann, dann verarbeite die Daten in einer Schleife. Gibt es einen eindeutigen Schlüssel (z. B. ID = 1:n), dann nimm immer ca. 10000 Sätze, also ID von 1 bis 10000, dann ID von 10001 bis 20000, ...
Auch wenn das funktioniert, bleibt dann immer noch das Performanceproblem...
Das liegt aber eventuell nur an der schier unüberschaubaren Datenmenge. Vermutlich haben beide Seiten nicht genug Arbeitsspeicher und müssen deshalb auf ihre Festplatten auslagern. Und die sind nun mal halt nicht unbedingt das schnellste Speichermedium. Wird virtueller Speicher genutzt (also Speicher, der physikalisch nicht vorhanden ist) wird's langsam.

Verarbeitungsmengen so wählen, dass der physikalische Speicher immer ausreicht, dann kann 1000 Mal ein Tausendstel durchaus schneller sein, als einmal alles, was ggfls. dann auch nur nach (gefühlten) Stunden mit 'ner Fehlermeldung scheitert.
  Mit Zitat antworten Zitat
hoika
Online

Registriert seit: 5. Jul 2006
Ort: Magdeburg
8.276 Beiträge
 
Delphi 10.4 Sydney
 
#13

AW: TAdoTable.Open() sprengt Arbeitsspeicherlimit

  Alt 9. Okt 2024, 06:47
Hallo,
forwardonly als CursorType?

https://stackoverflow.com/questions/...le-into-memory
Heiko
  Mit Zitat antworten Zitat
Benutzerbild von Jasocul
Jasocul

Registriert seit: 22. Sep 2004
Ort: Delmenhorst
1.354 Beiträge
 
Delphi 11 Alexandria
 
#14

AW: TAdoTable.Open() sprengt Arbeitsspeicherlimit

  Alt 9. Okt 2024, 06:56
Ich würde das überhaupt nicht mit Delphi lösen, sondern auf dem SQL-Server einen Zugriff auf die Access-Datenbank einrichten. Anschließend wird der Abgleich auf dem SQL-Server gemacht. Dafür bietet sich eine Stored Procedure an. Das dürfte um ein Vielfaches schneller sein und um die Speicherverwaltung kümmert sich SQL-Server.
Allerdings setzt das Kenntnisse in SQL voraus. Falls die bei dir nicht ausreichend sind, solltest du dafür jemanden beauftragen. Das spart vermutlich dennoch mehr Zeit und Kosten ein, als du jetzt für den Umbau in Delphi investieren musst. Ich gehe aber davon aus, dass eine Firma, die einen SQL-Server betreibt, auch jemanden hat, der über ausreichend SQL-Kenntnisse verfügt. Somit blieben die Kosten zumindest im Haus.
Eine Stored Procedure auf dem SQL-Server kannst du dann auch mit Delphi starten.
Peter
  Mit Zitat antworten Zitat
Benutzerbild von haentschman
haentschman

Registriert seit: 24. Okt 2006
Ort: Seifhennersdorf / Sachsen
5.388 Beiträge
 
Delphi 12 Athens
 
#15

AW: TAdoTable.Open() sprengt Arbeitsspeicherlimit

  Alt 9. Okt 2024, 07:13
Moin...

Zitat:
...seit einigen Jahren kann es aber auch SQL Server.
Wie wäre es die Anwendung grundsätzlich auf MSSQL laufen zu lassen und eine Replikation einzurichten. Die kümmert sich um die Daten...was wo hin muß...
https://learn.microsoft.com/de-de/sq...l-server-ver16

* Filter einrichten - jeder Abonnent bekommt nur das was er sehen darf
* Die komplette Replikation kann als Script gespeichert werden zum Neuaufbau der Replikation.
* Wir machen die Synchronierung der Daten zwischen den Filialen damit. Die Niederlassung schreibt was lokal rein, in "sekundenschnelle" ist die Information in der "Zentrale"...
* Wenn mal ein Abonnent "kaputt" ist, dann reorganisiert die Replikation die komplette Datenbank aus dem Verleger neu.
Miniaturansicht angehängter Grafiken
replikation.jpg  

Geändert von haentschman ( 9. Okt 2024 um 07:29 Uhr)
  Mit Zitat antworten Zitat
AxelO

Registriert seit: 1. Okt 2024
Ort: Rheinland/NRW
6 Beiträge
 
Delphi 10.3 Rio
 
#16

AW: TAdoTable.Open() sprengt Arbeitsspeicherlimit

  Alt 22. Okt 2024, 11:39
Sorry, dass ich so lange nicht geantwortet habe. Erstmal danke für die vielen Antworten und Informationen.

Die Query kann auch .Edit und .Append?
Natürlich ... so lange das SELECT der Query ein Rückschreiben erlaubt.
Notfalls kann man aber auch eigene INSERT/EDIT/DELETE-Statements angeben, wenn es gewisse Sonderfälle erfordern.
Eine Query mit SELECT * FROM deinetablle entspricht der Table.
Lädt also auch ALLES.
Das habe ich jetzt mal ausprobiert und dabei hat sich dann herausgestellt, dass der "serverseitige Cursor" (clUseServer) tatsächlich nur mit TAdoQuery funktioniert, aber nicht mit TAdoTable. Zumindest für meine Kombination aus DB, Provider usw. kann ich das so sagen: Wo eine Table selbst mit clUseServer wie oben beschrieben endlos lange lädt bis an's Limit, kommt eine Query auf das "select * ..." hin sofort zurück und braucht keinen lokalen Speicher. Und auch .Edit() und .Append() funktionieren. So hatte ich mir das vorgestellt.

Dafür dauert dann das .Locate() viel länger. Wenn in einer Query zu vielen Datensätzen positioniert werden muss, wartet man dann eben auch lange. Ich glaube aber, ich kann einen guten Kompromiss finden, bei welchen Tabellen ich mit clUseServer arbeite und bei welchen besser mit clUseClient.

Auch zu der Variante mit SQL "Merge" habe ich experimentiert. Das Fiese dabei ist ja, dass das nicht zwischen verschiedenen Datenbanken geht, die einzumergenden Daten müssen also schon in der Ziel-DB sein. Das kriege ich zwar mit einer leeren Puffertabelle mit derselben Struktur hin und mache dann das Merge zwischen der Puffertabelle und der Zieltabelle. Das ist dann wirklich sensationell schnell . Aber anschließend sind die Datensätze der Zieltabelle nicht mit den anderen Ziel-DB-Tabellen verknüpft, weil die Datensätze dort ja andere IDs haben. Statt eines einzigen "Merge" müsste ich dann wohl jeden Datensatz einzeln mergen und dabei die Ziel-IDs der anderen Tabellen als Parameter angeben, oder wie? Und die Puffertabelle(n) ist/sind ja auch nicht gerade elegant.

Moin...
Wie wäre es die Anwendung grundsätzlich auf MSSQL laufen zu lassen und eine Replikation einzurichten. Die kümmert sich um die Daten...was wo hin muß...
https://learn.microsoft.com/de-de/sq...l-server-ver16

* Filter einrichten - jeder Abonnent bekommt nur das was er sehen darf
* Die komplette Replikation kann als Script gespeichert werden zum Neuaufbau der Replikation.
[...]
Ja, liest sich auch gut. Aber die Quelltabellen stehen hier nicht von vornherein fest, sondern werden von den Anwendern aus verschiedensten Verzeichnissen interaktiv ausgewählt und ad hoc auf den SQL Server kopiert. Und die Lernkurve mit der Replikation würde ich mir auch gerne erstmal sparen. Ich bin von Hause aus kein Datenbankprogrammierer.

Ich würde das überhaupt nicht mit Delphi lösen, sondern auf dem SQL-Server einen Zugriff auf die Access-Datenbank einrichten.
Hier gilt dann auch wieder das Argument mit der Ad-hoc-Auswahl einzelner, wild verstreuter Access-Datenbanken. Die müsste man ja jedesmal einzeln einrichten.

Zitat:
Anschließend wird der Abgleich auf dem SQL-Server gemacht. Dafür bietet sich eine Stored Procedure an. Das dürfte um ein Vielfaches schneller sein und um die Speicherverwaltung kümmert sich SQL-Server.
Allerdings setzt das Kenntnisse in SQL voraus. Falls die bei dir nicht ausreichend sind, solltest du dafür jemanden beauftragen. Das spart vermutlich dennoch mehr Zeit und Kosten ein, als du jetzt für den Umbau in Delphi investieren musst. ... Eine Stored Procedure auf dem SQL-Server kannst du dann auch mit Delphi starten.
Mit einer kleinen Stored proc hatte ich auch mal kurz experimentiert und es auch geschafft, die von Delphi aus aufzurufen. Allerdings müsste ich dann die Identitätsprüfung komplett neu in SQL selber programmieren und die ist reichlich verzwickt und verschachtelt. Für den Originalprogrammierer dieses Algos wäre es sicher machbar, aber ich habe das Projekt schon von seinem Nachfolger übernommen, der sich selber nicht da rantraute...

Zitat:
Ich gehe aber davon aus, dass eine Firma, die einen SQL-Server betreibt, auch jemanden hat, der über ausreichend SQL-Kenntnisse verfügt. Somit blieben die Kosten zumindest im Haus.
Im Prinzip richtig, aber den Server betreibt ja der Kunde und dann müssten wir ihm den Algo offenlegen - und das wollen wir auch wieder nicht.

Habe ich mal kurz probiert und hat überhaupt nicht funktioniert, es entstanden lauter Dubletten.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 2     12   

 

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:07 Uhr.
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