MS SQL mit ODBC oder direkter FIrbeBird Zugriff, 2. Meinung?!

ny_unity

SQL-Guru
Beiträge
208
Hallo Leute,

ich stehe aktuell vor einem Problem, wo ich mal eine zweite oder dritte Meinung brauche...
Erstmal der Sachverhalt:
  1. Ich gehe im MS SQL über einen Linked Server auf eine FireBird Datenbank. Alle Abfragen werden mit einem ODBC-Treiber realisiert.
  2. Die Views des MS-SQL werden Webbasierend mit Codecharge dargestellt/verarbeitet
  3. Die Daten werden letztendlich über den Weg von Zwei ODBC-Wegen dargestellt, zu erst Codecharge ODBC zu MS_SQL View und von dort per ODBC zur Firebird-Datenbank
  4. Meine derzeitigen Abfragen basieren auf folgenden Format:
    Code:
    Select * from OPENQUERY(Firebird-DB, ' Select Feld1 from Table1 where Feld1 = 2')
    , also selektriere alles FROM Firebirdstatement.
Da die Abfragengröße bei gewissen Abfragen enorm ist und die Laufzeit bei 3-6 Sekunden über den ODBC ist, muss ich eine andere Lösung finden.

Ich habe mir dabei 3 Sachen überlegt, wobei ich Tipps bei der Realisierung benötige:
  1. Die Firebird-DB wird repliziert - und das alle paar Sekunden, um möglichst einen Echzeitsystem zu haben - hier dann Lokal die Abfragen einbinden, das spart den Weg des ODBC. Frage ist, wie viel CPU Last wird auf dem Server etwa verbraucht, wenn die DB alle par Sekunden repliziert wird, DB Größe liegt bei 3-4GB - oder man lagert nur die benötigten Tabellen aus, es handelt sich dabei um maximal 10 Tabellen.
  2. Kann man den MS-SQL View so abändern, dass man einen Filter in das FROM-Statement übergibt? Sprich
    Code:
    Select * from OPENQUERY(Firebird-DB, ' Select Feld1 from Table1 where Feld1 = Parameter1') where Parameter1
  3. Man legt eine 2. Firebirddatenbank an, die nur die Abfragen enthält, so bleibt man im gleichen System, Firebird zu Firebird und nicht MS-SQL zu Firebird. Aber ob das Laufzeitveränderungen bringt, weiß ich nicht.
Ja, so weit zum Thema, habt Ihr Tipps oder Anregungen oder eventuell noch ein Lösungsvorschlag?

Vielen Dank,

Erik
 
Werbung:
Schwierig zu beurteilen da ich Firebird nicht kenne. Eine WHERE Bedingung übergibst du ja schon mit OPENQUERY, da braucht deine View nicht die selbe WHERE Bedingung nochmal. Über wieviele Zeilen / Spalten reden wir denn hier bei deiner 3-6 Sekunden Abfrage? Und wie lange dauert diese Abfrage mit den selben Parametern unter Firebird? Hat Firebird passende Indexe auf der Tabelle?
 
bei der 3-6 Sekunden Abfrage sprechen wir von ~ 3500 Rows... Bei der Web-Darstellung brauch ich aber nur max 20. Problem jetzt ist, dass ich im Firebird-Statement erstmal alle Datensätze selektiere, im MS-SQL aber nur die benötigten anzeigen lasse - Problem, es ist immer die gleiche Laufzeit, da ja trotzdem alle abgefragt werden.
Beispiel:
Select * From (Firebird-Statement) where Kunde = 1
Ich bekomme im MS-SQL nur Kunde 1 angezeigt, der Firebird ruft trotzdem alle ab. Es müsste also so passieren, dass Select * From (Firbirdsstament mit where Parameter1) where Parameter1. Der Parameter1 wird durch Eingabe auf der Webseite durch Codecharge weitergegeben, aber das soll nicht das Problem sein, Problem ist die Syntax von MS-SQL mit Parameterübergabe ins Firebird-SQL...

Firebird hat passende Indexe... Die Abfrage direkt auf der Firebird-DB ohne ODBC dauert 0,2 Sekunden, mit einfachen ODBC, also beispielsweise lass ich den Firebird-SQL über den ODBC Manager laufen, dauert es 3,2Sekunden, bei MS-SQL zu Firebird etwa 5s.

gruß

Erik
 
Huhu,

ich nochmal, also ich bin jetzt so weit, das ich versuche, die parameter in das Firebird-Statement zu geben.
Syntax:
Code:
declare @v1 varchar(max)

EXEC('SELECT * FROM OPENQUERY (<linkedserver>, ''SELECT * FROM <table> WHERE <column> = ''''' + @v1 + ''''''')')

Das klappt ganz gut, Frage jetzt ist, wie deklariere ich einen Wert, der alle anzeigt? Beispielsweise es wird Kundennummer 1 eingegeben, dann ist klar, dann ist v1 = 26, doch wird nichts angegeben, sollen alle Datensätze angezeigt werden. Welchen Wert bekommt v1?

Danke und Gruß

Erik
 
Also ich habe mal innerhalb von MSSQL mit Verbindungsserver zu MSSQL 3 Abfragen getestet.

Lokal:
Code:
SELECT    *
FROM    tabelle

Remote:
Code:
SELECT    *
FROM    OPENQUERY(VERBINDUNGSSERVER, 'SELECT * FROM [DB].[dbo].[tabelle]')

SELECT    *
FROM    [DBSERVER].[DB].[dbo].[tabelle]
Alle 3 Querys liefern ca. 367.000 Zeilen in 12-13 Sekunden. Mit WHERE Klausel verhalten sie sich auch völlig gleich, es werden nur die angefragten Zeilen zurück geliefert. Der Ausführungsplan setzt auch 100% der Kosten auf die eigentliche Tabellenabfrage. Vieleicht gibt dir die Option "tatsächlichen Ausführungsplan einschließen" im MSSQL Studio mehr Information.

Ich denke das Problem liegt entweder bei Firebird oder warscheinlicher beim ODBC Treiber für Firebird. Du solltest mal eine andere Version testen, auch wenn du vieleicht schon die neuste hast. http://www.firebirdsql.org/en/odbc-driver/
Hier noch ein ähnliches Problem: http://forums.devshed.com/firebird-...ird-database-query-extremely-slow-483271.html

Deinen Workarround kann ich natürlich nachvollziehen aber die ganze DB alle paar Sekunden zu kopieren halte ich für die ungünstigste Variante.
 
Hallo,

danke für deine Mühe.

Was hälst du von der Parameterübergabe? Das klappt eigentlich ganz gut, nur gibts es den Fall, das alle Datensätze des Views angezeigt werden soll, also soll der Parameter so übergeben werden, das alle Datensätze selektiert werden sollen bzw. der Filter ausfällt.

Jetzt ist es so:
Code:
declare @v1 varchar(max) = 10000
EXEC ('SELECT * FROM OPENQUERY (Firebird-DB, ''select KUNDEN.KUNDENNR FROM KUNDEN  WHERE KUNDEN.KUNDENNR = ''''' + @v1 + ''''''')')

Problem jetzt, wie deklariere ich v1 so, dass wenn kein Wert übergeben wird, alle Datensätze abgefragt werden, in der Art: wenn @v1 is null, dann kein Filter, ansonsten @v1

Danke

Erik
 
Also das Query sollte man immer möglichst weit Einschränken daher am besten alle Parameter übergeben die sich anbieten. Wiso deine Zahl 10000 ein VARCHAR(max) und kein INT oder SMALLINT ist ist mir allerdings nicht ganz klar :)

Code:
WHERE    KUNDEN.KUNDENNR = @v1
OR        @v1 IS NULL
... müsste gehen.
 
Code:
declare @v1 int
set @v1 = 146724
das geht, Where-Klausel:
Code:
WHERE ''''' + @v1 + ''''' is null or  t1.KUNDENNR = ''''' + @v1 + '''''''
doch wue trage ich jetzt das Set ein, wenn v1 null ist, so dass alle Kundennummr genommen werden?
 
Wenn @v1 = NULL ist, wird das auch gesetzt. Gleicht er dann @v1 IS NULL ab ergibt das in jeder Zeile TRUE und du müsstest alle Spalten bekommen. @v1 darf aber nicht in Strichen stehen weil 'NULL' IS NULL nicht funktioniert. Wenn @v1 ein INT ist muss er das aber auch nicht. Ein VARCHAR schon. Irgendwie so müsste es gehen:
Code:
declare @v1 int
set @v1 = 10000
EXEC ('SELECT * FROM OPENQUERY (Firebird-DB, ''select KUNDEN.KUNDENNR FROM KUNDEN  WHERE ' + @v1 + ' is null or  t1.KUNDENNR = ' + @v1 + ')''')
 
Code:
declare @v1 int
set @v1 = NULL
EXEC ('SELECT * FROM OPENQUERY (MAND, ''select KUNDEN.KUNDENNR FROM KUNDEN WHERE ' + @v1 + ' is null or  KUNDEN.KUNDENNR = ' + @v1 + ' '')')

Der OLE DB-Anbieter 'MSDASQL' für den Verbindungsserver 'FB' hat die Meldung '[ODBC Firebird Driver][Firebird]Dynamic SQL Error
SQL error code = -104
Token unknown - line 1, column 43
is' zurückgeben.
Meldung 7321, Ebene 16, Status 2, Zeile 1
Fehler beim Vorbereiten der select KUNDEN.KUNDENNR FROM KUNDEN WHERE is null or KUNDEN.KUNDENNR = -Abfrage zur Ausführung für den OLE DB-Anbieter 'MSDASQL' für den Verbindungsserver 'FB'.

Wenn wir das noch gelöst bekommen, bin ich happy :)
 
Ich erzähl auch wirres Zeug heute...
Code:
declare @v1 int
set @v1 = 10000
EXEC ('SELECT * FROM OPENQUERY (Firebird-DB, ''select KUNDEN.KUNDENNR FROM KUNDEN  WHERE ' + isnull(cast(@v1 AS VARCHAR(20)),'NULL') + ' is null or  t1.KUNDENNR = ' + cast(isnull(@v1,0) AS VARCHAR(20)) + ')''')
 
hey ukulele,

mit der null-variante das wäre perfekt, klappt aber immer noch nicht... falsche synthax

Code:
declare @v1 int
set @v1 = -1
EXEC ('SELECT * FROM OPENQUERY (MAND, ''select KUNDEN.KUNDENNR FROM KUNDEN WHERE ' + @v1 + ' = -1 or  KUNDEN.KUNDENNR = ' + @v1 + ' '')')
Ich werd einfach es so machen, dass wenn Der Filter in der Webseite null ist, also leer, soll an den View -1 übergeben werden, so gehts ja auch :-)

Aber das mit null wäre das non plus ultra, wenn ich von der Webseite gleich null in Filter geben kann...

vielen Dank für deine Mühe
 
Code:
declare @v1 int
set @v1 = 10000

EXEC ('SELECT * FROM OPENQUERY (Firebird-DB, ''select KUNDEN.KUNDENNR FROM KUNDEN  WHERE ' + isnull(cast(@v1 AS VARCHAR(20)),'NULL') + ' is null or  t1.KUNDENNR = ' + cast(isnull(@v1,0) AS VARCHAR(20)) + '''')
 
Werbung:
Ne es fehlt nur schon wieder die scheiss hintere Klammer...
Code:
EXEC ('SELECT * FROM OPENQUERY (Firebird-DB, ''select KUNDEN.KUNDENNR FROM KUNDEN  WHERE ' + isnull(cast(@v1 AS VARCHAR(20)),'NULL') + ' is null or  t1.KUNDENNR = ' + cast(isnull(@v1,0) AS VARCHAR(20)) + ''')')
 
Zurück
Oben