Information ausblenden
Willkommen im Forum für alle Datenbanken! Registriere Dich kostenlos und diskutiere über DBs wie Mysql, MariaDB, Oracle, Sql-Server, Postgres, Access uvm

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

Dieses Thema im Forum "Microsoft SQL Server" wurde erstellt von ny_unity, 17 Februar 2014.

  1. ny_unity

    ny_unity Datenbank-Guru

    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
     
  2. ukulele

    ukulele Datenbank-Guru

    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?
     
  3. ny_unity

    ny_unity Datenbank-Guru

    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
     
  4. ny_unity

    ny_unity Datenbank-Guru

    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
     
  5. ukulele

    ukulele Datenbank-Guru

    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.
     
  6. ny_unity

    ny_unity Datenbank-Guru

    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
     
  7. ukulele

    ukulele Datenbank-Guru

    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.
     
  8. ny_unity

    ny_unity Datenbank-Guru

    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?
     
  9. ukulele

    ukulele Datenbank-Guru

    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 + ')''')
     
  10. ny_unity

    ny_unity Datenbank-Guru

    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 + ' '')')
    
    Wenn wir das noch gelöst bekommen, bin ich happy :)
     
  11. ukulele

    ukulele Datenbank-Guru

    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)) + ')''')
     
    ny_unity gefällt das.
  12. ny_unity

    ny_unity Datenbank-Guru

    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
     
  13. ukulele

    ukulele Datenbank-Guru

    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)) + '''')
     
  14. ny_unity

    ny_unity Datenbank-Guru

    Muss isnull nicht auch in hochkomma stehen?
     
  15. ukulele

    ukulele Datenbank-Guru

    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)) + ''')')
     
Die Seite wird geladen...

Diese Seite empfehlen

  1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies.
    Information ausblenden