Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   query.open blockiert (https://www.delphipraxis.net/177449-query-open-blockiert.html)

brechi 7. Nov 2013 08:34

Datenbank: MSSQL • Version: alle • Zugriff über: Zeos/Ado/AnyDac

query.open blockiert
 
Hallo,
ich habe verschiedene Komponenten ausprobiert, bei ZEOS/ADO blockiert ein Query.Open bis die kompletten Daten uebermittelt wurden, bei AnyDAC nicht.

Delphi-Quellcode:
  qry.sql.text := 'SELECT * FROM GROSSE_TABELLE';
  qry.open; // <-- erst fertig wenn die Daten uebermittelt wurden bei ZEOS/ADO, schnell bei AnyDAC
  while not qry.eof do begin
    // zeitintensive Berechnung
    qry.next; <-- vermutlich: schnell bei ZEOS/ADO, blockierend bei AnyDAC
  end;
Kann man das Verhalten von AnyDAC irgendwie bei ZEOS/ADO einstellen? Ich moechte die Daten schon verarbeiten, auch wenn diese noch nicht komplett uebertragen wurden (qry.next sollte dann blockieren). Da Uebertragung und Berechnung gleich lange dauern, wuerde es somit quasi parallel ausgefuehrt. Da im Moment das Open bei ZEOS/ADO blockiert dauert alles doppelt so lange...

Ich moechte ungern alles auf Events umstellen (ExecuteOption auf adAsyncExecute) da ich dann selbst den Main/Read-Thread synchonisieren muss.

Edit:
AnyDAC bzw. FireDAC ist mir zu teuer (D2007 Prof Upgrade bei mehreren Nutzern) und diese werden auch nicht mehr supported fuer Delphi2007.
Waere auch mit guenstigen Alternativen zu frieden.

Bernhard Geyer 7. Nov 2013 09:00

AW: query.open blockiert
 
Zitat:

Zitat von brechi (Beitrag 1234821)
Hallo,
ich habe verschiedene Komponenten ausprobiert, bei ZEOS/ADO blockiert ein Query.Open bis die kompletten Daten uebermittelt wurden, bei AnyDAC nicht.

Kann man das Verhalten von AnyDAC irgendwie bei ZEOS/ADO einstellen? Ich moechte die Daten schon verarbeiten, auch wenn diese noch nicht komplett uebertragen wurden (qry.next sollte dann blockieren).

Kein Problem. Du musst bei ADO die Curserlocation auf clUseServer stellen (Oder ein anderes Property was ich aktuell nicht weiß auf "AsncFetch")
Bei clUseServer belastet man aber den Server erheblicher da er ja die Ergebnismenge noch weiter auf dem Server vorhalten muss.

Zitat:

Zitat von brechi (Beitrag 1234821)
Da Uebertragung und Berechnung gleich lange dauern, wuerde es somit quasi parallel ausgefuehrt. Da im Moment das Open bei ZEOS/ADO blockiert dauert alles doppelt so lange...

Mit clUseServer könnte es u.U. noch länger dauern. Da wäre dann der Asnchrone Fetch vermutlich besser.

Zitat:

Zitat von brechi (Beitrag 1234821)
AnyDAC bzw. FireDAC ist mir zu teuer (D2007 Prof Upgrade bei mehreren Nutzern) und diese werden auch nicht mehr supported fuer Delphi2007. Waere auch mit guenstigen Alternativen zu frieden.

Die Devart (http://www.devart.com/de/) kosten zwar einiges, sind aber ihr Geld wert.
Wenn du etwas Zeit und Gehirnschmalz investierst kannst du auch versuchen die dbGo-Wrapper von Delphi zu umgehen und direkt mit der COM-Schnittstelle arbeiten. Bring auch einiges an Performance.

Uwe Raabe 7. Nov 2013 09:03

AW: query.open blockiert
 
Bei AnyDAC ist standardmäßig ein FetchOnDemand mit einer RowsetSize von 50 aktiv. Damit werden beim Open nur die ersten 50 Datensätze geladen. Inwieweit andere Zugriffskomponenten sowas anbieten und wie, kann ich nicht sagen.

brechi 7. Nov 2013 09:58

AW: query.open blockiert
 
Wenn CursorLocation clUseServer ist, dann blockiert "Open" erstmal nicht mehr, aber bei dem x. Query dauert das setzen des SQL-Textes sehr lange:

Delphi-Quellcode:
    Result.SQL.Clear;
    Result.SQL.Add(_SQL);

Intern wird dann:

  ADODB.InternalRefresh
// mit
  RefreshFromOleDB

// aufgerufen, wobei
   if Assigned(CommandPrepare) then CommandPrepare.Prepare(0);

// ewig dauert
Das kann ich also leider nicht verwenden. ExecuteOption AsyncFetch liefert die Daten in einem Extra-Thread, wobei ich mich dann wieder um Synchronisation keumemrn musss, das ist zu viel Aufwand (es werden dann die extra Events aufgerufen).

brechi 11. Nov 2013 08:31

AW: query.open blockiert
 
Habe mal SDAC (UniDAC) getestet, auch dort blockiert das "Open", selbst wenn FetchAll = False ist.
Weitere Vorschläge:?: (am liebsten fuer ADO)

EgonHugeist 11. Nov 2013 21:51

Hi brechi,

mit ADO selbst werden(soweit mir bekannt) immer alle geladen und konvertiert. Das TADORecorSet arbeitet grundsätlich mit einem full-fetch. All Daten werden via OLE-Variant bereit gestellt. Unglaubliche performance Bremse.

Zeos bietet dir auch den Zugriff über ntwdblib.dll (Protocoll: mssql) oder FreeTDS(diverse Versionen). Nativer Zugriff, jedoch ansi-basierend und bringt auch Tücken mit sich. Das TDS (tabular-data-stream) Protocol läßt keine NClob fetches ohne cast zu(der Grund für die OLE-DB Interpetation). Also schau mal ob du da mehr Erfolg hast und dies deinen Anforderungen entspricht... MSSQL selber ist a bisl, naja leistungsfähig ja, jedoch nur im reiner Forward-Only mode. Nahezu alle RDBM's, außer SQLite, lassen nachträgliches navigiern innerhalb der der Daten-Mengen zu. MSQQL jedoch in keiner Weise, (soweit mir bekannt -> Klärt mich auf und ich bau's ein). Jedoch lädt Zeos dann die Daten erst, wenn du eine weiter Zeile auslesen willst.

Werd jedoc mal reinschauen(ADO), ob da nicht doch irgendwie etwas zu ändern geht und evt. völlig falsch liege -> ADO.

Gruß, Michael

jaenicke 12. Nov 2013 05:15

AW: query.open blockiert
 
Ein ähnliches Problem habe ich gerade über DataSnap gelöst. Dort kommt dazu, dass ich nicht direkt an die Datenbank herankomme und ausschließlich (AFAIK) komplette DataSets bekomme.

Gelöst habe ich das indem ich mir (es ist ein MS SQL Server) mit DBCC SHOW_STATISTICS die Verteilung der Daten auf der Indexspalte abfrage und dann aus diesem Histogramm einen Abfrageplan erstelle, basierend auf den ermittelten statistischen Werten der aktuellen Verbindungsqualität usw.
Dann frage ich im Thread die einzelnen Pakete ab und hänge diese (in meinem Fall ist das am besten) synchronisiert in die Zieltabelle. Diese wiederum wird dann z.B. für die Anzeige in einer VirtualStringTree benutzt.

In deinem Fall würde es bei einem solchen Vorgehen reichen immer die Datasets mit den einzelnen Paketen weiterzureichen. Und du müsstest die Verarbeitung nicht einmal mit dem Hauptthread synchronisieren, sondern könntest diese auch gleich in Threads machen.

brechi 12. Nov 2013 07:23

AW: query.open blockiert
 
Hi, danke fuer eure Antworten.
Ich moechte ungern viel Zeit in die Umstellung der Abfragen investieren, zumal es mit AnyDAC ja auch ohne geht. (eventl. kauf ich die doch fuer mich und compiliere dann nur die finale Version damit).

Bisherige erstmal zufriedenstellende Funktion ist folgende:

Delphi-Quellcode:
    if (FQueryCount = 1) then
      Result.CursorLocation := clUseServer
    else
      Result.CursorLocation := clUseClient;
    if _ReadOnly then begin
      Result.ExecuteOptions := [eoAsyncFetch];
      Result.LockType := ltReadOnly;
    end;
cluseServer blockiert Open nicht, wird aber EXTREM langsam wenn dies innerhalb einer verschachtelten Funktion aufgerufen wird (2 offene Verbindungen ubder die Connection). eoAsyncFetch funktioniert mit cluseClient (Open blockiert nicht) ist aber trotzdem viel langsamer als clUseServer. Ggf. kann ich die Schleifen noch umstellen... Also moeglichst minimaler Aufwand, sonst kann ich gleich das ganze Programm umstellen ;)

tsteinmaurer 12. Nov 2013 07:47

AW: query.open blockiert
 
Vielleicht ist es einfach auch nur das Problem, dass der Snapshot Isolation für READ COMMITTed Transaktionen per Default nicht aktiviert ist, d.h. dass dein lesender Zugriff durch eine noch nicht committete schreibende Transaktion blockiert ist.


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:58 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