orausdo
Goto Top

Zugriff von SQL Server 2012 auf Intersystems Cache DB - Abfrage dauert ewig bzw. bring keine Ergebnisse

Moin liebe Admins,

ich habe mal wieder eine Frage.

Wie oben schon genannt starte ich eine Abfrage von SQL Server aus:

Es ist eine insert into select abfrage die über einen Verbindungsserver auf eine Cache DB zugreift.
Dabei werden zwei Cache Tabellen gejoint.
Das Ergebnis der Abfrage soll die Daten in eine vorhandene SQL Server Tabelle wegschreiben.

Leider dauert es sooo lange, dass ich sie schon abbreche bevor sie Daten liefert. Habe auch schon 2 Stunden gewartet. face-wink

Weiß einer eine Lösung wie man so eine Abfrage beschleunigen kann oder wie sie gestaltet werden muss?
Gibt es eigentlich noch eine andere Lösung als über einen Verbindungsserver zu gehen ähnlich wie die verlinkten Tabellen wie in Access?

Bin für alle Antworten dankbar.

Gruss DerO

Content-ID: 211199

Url: https://administrator.de/contentid/211199

Ausgedruckt am: 22.11.2024 um 19:11 Uhr

Grinskeks
Lösung Grinskeks 11.07.2013, aktualisiert am 16.02.2016 um 16:00:09 Uhr
Goto Top
Hallo,

vielleicht versuchst du mal folgendes:


Select * into #tbl1 from cache table 1
Select * into #tbl2 from cache table 2

Insert into select .. from #tbl1 <join> #tbl2

drop table #tbl1
drop table #tbl2


Also quasi ein Ansatz, zunächst die Tabellen 1zu1 physisch oder in TempDB als temporäre tabellen zu übernehmen. Im Anschluss die Query aufsetzen (evt. indizes setzen, je nach Performance und dann ausführen.

Das Wiederherstellungsmodell würde ich zuvor auf "simple" setzen, damit das Transaktionsprotokoll nicht voll läuft.


Das ist aber alles mehr oder weniger Glaskugel, da keinerlei Infos zu Datenmenge, Hardware und Verbindungsdetails (Wan, Lan) bekannt sind.

Gruss

Grinskeks
orausdo
orausdo 12.07.2013 um 08:35:18 Uhr
Goto Top
Moin Grinskeks,

vielen Dank für Deine Antwort.

Du meinst hinterher joinen, wenn die Tabellen schon im SQL Server sind?
Das habe ich gestern auch schon angetestet.
Bei der einen Tabelle handelt es sich um die Kopfsätze und in der anderen sind die entsprechenden Positionen dazu.
Die Kopfsatztabelle geht recht schnell. Ca. 8000 Datensätze.
Bei der Positionstabelle hab ich keine Anzahl. Select auf einen Tag eingegrenzt dauert schon Monde...
Ich kann ne TOP 10000 machen, die geht. Aber alle DS für ein Datum keine Chance.

Wiederherstellungsmodell ist auf Massenprotokolliert.
Es handelt sich um einen W2k8R2 Server mit SQL2012DB am LAN mit 10,0 Gbit/s als VM

Kennst Du noch einen anderen Weg Abfragen über einen Verbindungsserver zu beschleunigen?
Gibt es verlinkte Tabellen ala Access in MS-SQL?

Vielen Dank für weitere Hilfe.

Gruss
DerO
Grinskeks
Grinskeks 12.07.2013 um 10:27:20 Uhr
Goto Top
Moin,

da kommt es schon auf die Query an. Wie ist dein Statement genau? Nutzt du OpenQuery, gibst du das Datum absolut an oder z.B. Getdate()?

Wie groß ist ein solcher Datensatz? Wenn du statt einem Select eine View machst, wie lange dauert es, diese zu öffnen? etc.


Gruss
Grinskeks
orausdo
orausdo 12.07.2013 um 10:50:38 Uhr
Goto Top
Moin,

hier das Statement: Datum ist absolut angegeben...

SELECT ‘0’ + TABELLE1.Filiale, TABELLE1.Lagernummer, TABELLE2.Positionsnummer, TABELLE2.Stornokennzeichen, Left(Warengruppe,2) AS WaGr, Right(Artikelnummer,8) AS Artikel, TABELLE2.Ausführung, TABELLE1.Erfassungsdatum, TABELLE2.Bestelldatum INTO Erzeugte_Tabelle
FROM TABELLE1 INNER JOIN TABELLE2 ON (TABELLE1.Lagernummer = TABELLE2.Lagernummer) AND (TABELLE1.Mandantenname = TABELLE2.Mandantenname)
WHERE ((TABELLE1.Erfassungsdatum=’12.07.2013‘) AND (TABELLE1.Mandantenname=‘0‘) AND (TABELLE1.Bestelltext=‘Irgendein_Text‘))
ORDER BY ‘0’ + TABELLE1.Bestellfiliale, TABELLE1.Lagernummer, TABELLE2.Positionsnummer, Left(Warengruppe,2), Right(Artikelnummer,8), TABELLE2.Ausführung;

Datenmenge Kopfsatztabelle = ca. 8000
Datenmenge zugehörige Positionstabelle = keine Anzahl da Ausführung zu lange dauert.

Du meinst eine View auf den Verbindungsserver? geht das wirklich? Warum sollte es damit schneller gehen Daten aus der Intersystems DB zu ziehen?

Vielen Dank für weitere Hilfe.

Gruss DER O
Biber
Lösung Biber 12.07.2013, aktualisiert am 16.02.2016 um 16:00:16 Uhr
Goto Top
Moin orauso,

genz sicher bin ich nicht, wo am ehesten für die Optimierung anzusetzen wäre, aber es scheint ja angebracht zu sein zu vermuten, dass auf den größeren Datenklumpen, die "Positionstabelle" ein Fullselert gemacht wird.
Dazu die Frage: was sind denn die "eigentlichen" fachlichen Schlüssel, über die die beiden Tabellen zusammenhängen sollten? Die beiden JOIN-Felder Lagernummer und Mandantenname scheinen es ja nicht zu sein.

Was ist den der identifizierende Schlüssel der "kopftabelle"? Sind da "Mandantname" und "Filliale" enthalten?

Und irgendwie geht bei dir - zumindest im geposteten Statement - etwas durcheinander.
Was oben in den ersten SELECT-Feldern "
SELECT ‘0’ + TABELLE1.Filiale" heisst, erscheint im (viel, viel zu langen!) Order by als " ‘0’ + TABELLE1.Bestellfiliale,".

Grüße
Biber
orausdo
orausdo 12.07.2013 um 13:14:43 Uhr
Goto Top
Moin Biber.

Was menist Du mit "eigentlichen fachlichen Schlüssel"

Der join läuft über die beiden Schlüsselfelder Lagernummer + Mandantename.

Diese sind auch in den Quelltabellen die Schlüssel.

Hast Recht. In der order by muss die Spalte natürlich auch Filiale heissen.
Aber das order by kann man auch ganz weglassen.
Hauptsache die Daten kommen in die SQL Server DB.

Die Abfragen kommen aus einer alten Access DB die nun auf einer SQL Server DB laufen soll.

Danke Dir für die Hilfe, wäre super wenn ich weitere Hilfe bekomme.

Gruss Der O
Grinskeks
Grinskeks 12.07.2013 um 18:02:04 Uhr
Goto Top
Versuch mal bitte folgendes

Set statistics io on;
set statistics time on;

SELECT * into #Tabelle2
FROM OPENQUERY(<linked server>,
'SELECT <Hier die benötigten Felder von Tabelle 2 rein> FROM Tabelle2') T2

Select * from #Tabelle2

Drop #Tabelle2

Es ist wichtig, dass das komplette Statement innerhalb der Openquery steht damit der verbundene Server komplett remote arbeitet. Das Order by sollte da nicht drin stehen - das kostet ordentlich performance und der Tabelle ist es egal, in welcher Reihenfolge die Inserts erfolgen.


Gruss

Grinskeks
orausdo
orausdo 15.07.2013 um 10:38:09 Uhr
Goto Top
Hi Grinskeks,

vielen Dank für Deine weitere Hilfe.

Hab es so versucht. Leider dauert die Abfrage allein bei DS Begrenzung auf TOP 1000 ca. 20 min.
Wenn ich ein normales Select Statement mit TOP 1000 ausführe dauert es 47 sec.

Die koplette Positionstabelle hat ca. 60.000 DS.
Die Abfrage mit inner join auf die Tabelle mit den Kopfdaten läuft auf dem SQL Server ins Leere bzw.unendlich lange.
Wenn ich das komplette Statement aus dem 3. Post in einer Access DB mit den beiden Tabellen als verlinkte Tabellen ausführe dauert es ca. 2-3 min und ich habe es Ergebnis aus dem Join.

Gibt es weitere Möglichkeiten die Abfrage auf den Verbindungsserver zu beschleunigen?

Vielen vielen Dank für weitere Hilfe.

Gruss Der O.
Biber
Lösung Biber 15.07.2013, aktualisiert am 16.02.2016 um 16:00:25 Uhr
Goto Top
Moin orausdo,

das kann doch nicht sein... bei der Laufzeit kannst du doch schneller die Datensätze mit einer Laubsäge neu erstellen.

Das interessiert mich langsam aber auch, was da warum schiefgeht...

Du holst dich letzten Endes, wenn ich das richtig zusammenfasse, aus einer lächerlichen Datenmenge von gesammt 60000 Positionsdaten viellecht ein Hundertsel (alle Positionen dieses Selects);

 SELECT  * from Tabelle2 where 
           Mandantenname ='0' and Lagernummer in   
        ( select distinct(lagernummer 
         FROM TABELLE1 
        WHERE (TABELLE1.Erfassungsdatum=’12.07.2013‘) 
             AND (TABELLE1.Mandantenname=‘0‘) 
             AND (TABELLE1.Bestelltext=‘Irgendein_Text‘)
  )

Das ist doch der eigentliche Rest der Positionsdaten, mit dem du joinen musst.
Wie viele Sätze werden bei dieser Unter-Abfrage geliefert und in welcher Zeit?

Oder geht das auch in die Grütze?

Grüße
Biber
orausdo
orausdo 15.07.2013 um 17:01:30 Uhr
Goto Top
Moin Biber,

danke dir für Deine Antwort.

Hab die Unterabfrage mal ausgeführt.
Sie dauerte 06:47 min und ergab 7367 Datensätze.
Nun gibt es zu den 7367 DS jeweils 1-n Positionen in der Pos.-Tabelle.
Wenn ich die ganz oben genannte Abfrage mit join und allem drum und dran in Access laufen lasse,
dann komme ich bei einer Anzahl von 7367 Kopfzeilen auf eine Gesamtmenge von 50848 Datensätze.
Jeweils 1-n Positionen zu einer Lagernumer.
Und das in 1 Minute.

Kann es am Verbindungsserver liegen?

Danke für Hilfe.

Gruss O
Biber
Lösung Biber 15.07.2013, aktualisiert am 16.02.2016 um 16:00:28 Uhr
Goto Top
Moin orausdo,

das sind keine Antwortzeiten, das sind Lieferzeiten.
Hab die Unterabfrage mal ausgeführt.
Sie dauerte 06:47 min und ergab 7367 Datensätze.
In dieser Zeit könnte ich auch die 7367 Zeilen vom Bremer Hauptbahnhof bis auf meinen Balkon bringen lassen.
Per Bus, Rikscha oder Bollerwagen. Und Zeit zum einzeln vorsingen wäre ja auch noch.

Ist eventuell denn das "Erfassungsdatum" im Access ein Datumsfeld und wird es nur durch deinen Textparameter '12.07.2013' irrsinnnig zeitaufwendig zwangsgecastet?
Oder ist da (in Acceess) noch ein drittes "verbindendes Feld" zwischen Tabelle1 und Tabelle2 , z.B. ein Datumsfeld ,als "Beziehung" hinterlegt

Anders gefragt: "Mandantenname" '0' und "Lagernummer" können doch in Tabelle1 nicht der identifizierende Schlüssel sein - diese Kombination muss es doch jede Woche wieder geben, oder nicht?..

Also - mag sein, dass der Verbindungsserver Zeit frisst, und auch mit dem allerersten "SELECT INTO Ergebnis, aber in einer sortierten Reihenfolge" hast du dat Dingen sicher unnötig gequält - aber derartige Antwortzeiten können nicht sein. Selbst wenn du noch parallel irgendwelche DVDs brennst auf dem Server.

Ich warte mal auf den Grinsekrümel...

Grüße
Biber
Grinskeks
Grinskeks 15.07.2013 um 21:13:40 Uhr
Goto Top
Hmm,

falls du bei deinen Queries immer nach dem Datum selected hast, solltest du dieses mal in eine Variable packen und als Datetime casten - nur zum Test.


Bringt das Query Tuning da nichts, dann

- versuchen wir etwas anderes: Linked Server Einstellungen checken

Setze mal
lazy schema validation on
und checke, ob collation compatible an ist.


Gruss
Grinskeks
orausdo
orausdo 16.07.2013 um 08:50:42 Uhr
Goto Top
Moin Biber und Grinskeks,

ich danke Euch für Eure Vorschläge.

Ja, dass Datum ist in der Quelle ein Datumsfeld.
Wie kann ich es denn umbauen?

Grinsekeks --> Wenn ich diese beiden Optionen setze geht gar nüscht mehr.
Die Lazy Option schmeisst sofort einen Fehler raus, da sie angeblich nicht in SQL 2012 unterstützt wird.
Wenn ich die Collation anlasse geht die Abfrage auf den Linked Server nicht mehr.

Gruss O.
Biber
Biber 16.07.2013 um 10:35:26 Uhr
Goto Top
Moin orausdo,

bitte prüfe nochmal meine Rückfragen und deine ntworten darauf.

Du hattest geschrieben:
Der join läuft über die beiden Schlüsselfelder Lagernummer + Mandantename.
Diese sind auch in den Quelltabellen die Schlüssel.

Das halte ich nach wie vor für unwahrscheinlich, dass der identifizierende Schlüssel in der "Kopftabelle" nur Mandantenname und Lagernummer beinhalten kann.
Dann darf doch - bei deiner Eingrenzund auf Mandantenname='0' nur ein Datensatz fü das Lager 4711 herausfallen, egal ob du Erfassungsdatum '12.07.2013' einschränkst oder nicht.

Und wenn als der verbindende Schlüssel in der Positionstabelle tatsächlich nur "Mandantenname+Lagernumme" wäre plus "Positionsnummer" als Differenzierungskriterium, dann macht das Statement natürlich immer einen Fullselct auese "große" Tabelle. Da sind doch dann aber auch Daten aus den Jahren 2010 bis 2012 dabei - das wird doch nirgends eingeschränkt.

Die Zusammenhänge sind mir nicht plausibel.

Wenn es tatsächlich so ist wie beschrieben, dass stelle doch mal einen (ggf. stilisierten) Beispielsatz für Mandanten'0' und Lagernummer 4711 und die dazugehörigen Positionsdaten zur Anschauung hier vor.

Grüße
Biber
orausdo
orausdo 16.07.2013 um 11:41:22 Uhr
Goto Top
Moin Biber,

Also, der join mit Mandant ist aus der ursprünglichen Access Abfrage und kann eigentlich weggelassen werden.
Wichtig ist die Beziehung zwischen den beiden Lagernummern.
Für die Lagernummer 10001 in der Tabelle Kopfzeilen gibt es 1-n Positionen in der Tabelle Positionen zu einem bestimmten Datum (hier zB: 11.07.2013).
Beim select auf die Kopftab mit Datum 11.07.2013 bekomme ich ca. 7367 DS.
In Verbund mit der Lagernummer von Kopftab auf PosTab sollten genau 50848 DS rauskommen.
Das ist die Anzahl die ich bekomme, wenn ich die Abfrage im Post vom 12.07.2013 um 10:50 Uhr in der alten Access DB laufen lasse.
Die gleiche Abfrage auf den SQL Server angepasst läuft halt ins Leere. Genau das ist mein Problem.

LbNr PosNr ArtNr ErfassungsDatum
10001 1 1888123456 11.07.2013
10001 2 1888123457 11.07.2013
10001 3 1888123458 11.07.2013
10001 4 1888123459 11.07.2013
10001 5 1888123460 11.07.2013
10001 6 1888123461 11.07.2013
10001 7 1888123462 11.07.2013
10001 8 1888123463 11.07.2013

LBNr in Kopftab = 10001 --> Alle Positionen der PosTab auf diese Nummer.

Kannst Du mir bitte noch sagen, wie ich das Datum am besten anpasse?
In der Quelle ist es ein Datumsfeld. Hab auch schon mit cast rumprobiert.
Bringt aber keine Verbesserung. Hast Du einen Tip?
Es gibt doch auch ODBC Datentypen fürs Datum, oder? Wie geht das?
Der Verbindungsserver ist ja über die ODBC Schnittstelle verlinkt...

Würde mich über weitere Hilfe freuen.

Gruss Der O.
Biber
Biber 16.07.2013 um 12:47:23 Uhr
Goto Top
Moin orausdo,

ein casten von Text (-> dein eingegebenes '11.07.2013' auf einen Date-Typ geht in meiner Erinnerung so:

convert(datetime, '11.07.2013', 104) -- 104 ist das Datumsformat dd.mm.yyyy

Dieses an die Stelle setzen, wo heute der String '11.07.2013' steht, im Statement die ORDER BY-clause umweltgerecht entsorgen und testen.

Grüße
Biber
orausdo
orausdo 16.07.2013 um 13:03:42 Uhr
Goto Top
Hi Biber,

dank für die Info.

Ich habe jetzt mehrere Versionen der Datumsübergabe probiert.
Allein um die 7k aus der KopfTab zu selecten braucht es immer um die 5 min.
Kannst Dir ja vorstellen wie es im Verbund mit der Postab ist... face-sad

Konntest Du mit meinem Post und dem Abfrag Ausschnitt etwas anfangen?

Thx.

Gruss orausdo
Biber
Biber 16.07.2013, aktualisiert am 21.07.2013 um 17:00:22 Uhr
Goto Top
Moin orausdo,

ich stehe verständnislos davor - ist mir vollkommen unerklärlich, was da schiefläuft.

Wenn ich es richtig interpretiere, dann schickst du über ODBC eine Abfrage auf die 2 Tabellen dieser ACCESS-Datenbank; der zurückkommende Resultset soll in eine Ergebnistabelle auf dem (fragenden) SQLServer geschrieben werden.

Da kann eigentlich nur begrenzt viel schiefgehen.
Und da du ja auch grundsätzlich Daten retour bekommst, kann ich nicht den Treiber als ungeeignet verdächtigen.

Tut mir leid, ich muss passen bzw. die Antworten von anderen abwarten.
Derartig langsame Abfragen kenne ich - selbst im Zusammenhang mit ACCESS- nicht.

Sorry
Biber
orausdo
orausdo 16.07.2013 um 14:07:37 Uhr
Goto Top
Hi Biber,

der alte Stand ist via ODBC eine Abfrage in Access auf eine Intersystems DB. Dauer wie beschrieben.... ca. 2-3 min
Neuer Stand soll werden: Gleiche Abfrage über einen Linked Server (auc ODBC) auf die gleiche Intersystems DB. Dauer bis zum Nimmerleinstag...!

Am besten ich mache ein Makro, dass mir die Abfrage in der Access DB ausführt,
die dann aus dem Ergebnis eine Datei generiert und irgendwo ablegt,
dann nehme ich sie und hau sie in den SQL Server rein..... face-wink

Kein Thema, Danke Dir sehr für Deine Bemühungen.

Grüsse von Orausdo
Grinskeks
Grinskeks 17.07.2013 aktualisiert um 21:45:17 Uhr
Goto Top
Hallo,
ich könnte Wetten, dass der SQL Server keine Indizes "sieht" über ODBC und deswenge so langsam sind. Jet Datenbanken (Access etc.) sind in diesem Fall flotter.

Wird der aktuellste Treiber vom ftp Server von Intersystems cache verwendet?

Gibt es SecurityTools, Firewalls etc. die die Connection / Ports bzgl. Performance beeinträchtigen?

Gruss
Grinskeks
orausdo
orausdo 18.07.2013 um 08:34:38 Uhr
Goto Top
Moin Ginsekeks,

weißt Du wie ich das von Dir beschriebene Problem mit den Indizies lösen kann?

Die aktuellsten Treiber von Cache sind installiert.

Wann könnte ich den an den Firewall Einstellungen ändern?

Thx.

Gruss DerO