2 Antworten Neueste Antwort am Aug 26, 2016 12:21 AM von file.maker@mybyte.ch

    Langsame SQL-Abfrage

    file.maker@mybyte.ch

      Hallo FM- und SQL-Cracks

      Mit der Start-Routine will ich ein Global-Feld, das in verschiedenen Tabellen vorkommen kann, mit der ID des Benutzers versehen, um meine FM-Lösung Multi-User-fähiger zu machen. Nicht alle Tabellen müssen diese ID haben. Es klappt tipptopp, einzig die Abfrage nach dem globalen ID-Feld in den FileMaker-System-Tabellen dauert spürbar eine Ewigkeit von 9 bis 10 Sekunden. Wie kann ich die Abfrage spürbar beschleunigen?

       

      Es geht darum, dass ich eine Liste von Tabellen erhalten will, in denen das Feld vorkommt. In den beiden Systemtabellen gibt es leider nur den Tabellennamen «TableName» als Schlüssel, und benötigen tu ich nur den Basistabellennamen «BaseTableName», da nur für diese Tabellen-Instanz ein «Alle Felder»-Layout existiert, das zwingend in meiner Lösung angelegt sein muss.

       

      Nachfolgend die funktionierende Formel zum Ausprobieren. Das Resultat ist genau das, was ich benötige, nur dauert es halt eine Ewigkeit.

       

      SetzeVar (

        [

          Feldname = "_ID_User_GLOBAL" ; // FELDNAMEN AENDERN MIT EUREM FELDNAMEN REICHT SCHON

          Start = ZeitStempel ( Hole( SystemDatum ) ; Hole( SystemUhrzeit ) ) ;

          Result = SQLAusführen ( "

            SELECT DISTINCT T.BaseTableName

            FROM   FileMaker_Tables T, FileMaker_Fields F

            WHERE  F.TableName=T.BaseTableName AND F.FieldName='" & Feldname & "'

          " ; "|" ; ¶ ) ;

          Stop = ZeitStempel ( Hole( SystemDatum ) ; Hole( SystemUhrzeit ) )

        ];

      Result

      & ¶ & Stop-Start // verbrauchte Zeit

      )

       

      Hab in der Where-Klausel auch schon andere Varianten ausprobiert. Performancemässig gibt es keinen Unterschied.

      WHERE

        (

          SELECT F.TableName

          FROM FileMaker_Fields F

          WHERE

            F.TableName = T.BaseTableName AND

            F.FieldName='_ID_User_GLOBAL'

        ) = T.BaseTableName

       

      Hier noch die Feld-Definitionen der beiden Systemtabellen:

      FileMaker_Tables

      • TableName
      • TableID
      • BaseTableName
      • BaseFileName
      • ModCount

        FileMaker_Fields

      • TableName
      • FieldName
      • FieldType (the SQL data type, not the FileMaker data type)
      • FieldID
      • FieldClass (Normal, Summary, Calculated)
      • FieldReps
      • ModCount

      Besten Dank für Eure Aufmerksamkeit!

      Gruss aus Zürich

      Hans

        • 1. Re: Langsame SQL-Abfrage
          file.maker@mybyte.ch

          Hab mir schon gedacht, dass ich hier eine ziemlich schwierige Frage stelle. Eigentlich geht es ja darum, dass ich Daten aus einer Tabelle abfrage, zur Hauptsache aber Suchkriterien aus einer anderen Tabelle verwende. Hinzu kommt noch die Filterung durch DISTINCT, um Redundanzen zu vermeiden. Selber weiss ich aus der Webprogrammierung mit MySQL und MSSQL, dass unsachgemässes SQL eine DB-Anwendung in die Knie zwingen kann, und das für eine halbe Stunde lang. Nun, mein SQL ist nicht so schlimm, und solche Umstände würde ich auch nie zulassen (andere aber schon, wie ich wie erwähnt feststellen musste).

           

          Nun, ich habe es geschafft, die Erzeugung der Liste auf 1 Sekunde oder vielleicht weniger herunterzubringen. Der Aufwand der Programmierung war zwar deutlich höher, und erst mit der 2. Alternative sind auch die nachfolgenden Prozesse deutlich verkürzt worden. Diese sind eine Subroutine meines Startskripts (nach Benutzer-LogIn), das mit allen Prozessen mehr als 500 Codezeilen umfasst (Umgebungsvariablen ermitteln, Log, Lizenzüberprüfung, Import/Export-Ordner, Datensicherung etc.). Die Ergebnis wird durch eine Kombination von SQL-Abfragen und einigen FileMaker-Scriptschritten und Funktionen erzeugt.

          Der genaueres darüber wissen will, kann mich ja persönlich anfragen.

          Gruss aus Zürich

          Hans

           

          # Liste Tabellen-Auftreten, in denen das globale User-ID-Feld angelegt ist

          Variable setzen [ $Tabellen.Instanzen ; Wert:

              /* Tabellen-Auftreten, in denen das globale User-ID-Feld angelegt ist */

              SetzeVar (

                  [

                      $Start = ZeitStempel( Hole( SystemDatum ) ; Hole( SystemUhrzeit ) ) ;

                      $Tabellen = "";

                      Query = "

                        SELECT    F.TableName

                        FROM      FileMaker_Fields F

                        WHERE     F.FieldName = '_ID_User_GLOBAL' AND F.TableName NOT LIKE 'ZAPP%'

                        ORDER BY F.TableName ASC  "

                  ];

                      //Query & ¶ & ¶ &

                      SQLAusführen ( Query ; "|" ; ¶  )

              )

          ]

          # ------------------------------

          # Tabellen-Instanzen (Liste) durchlaufen und Basis-Tabellenliste erzeugen

          # ------------------------------

          Variable setzen [ $Durchlauf ; Wert:

              /* Durchlaufbedingung & Iterator/Zaehler initialisieren */

              SetzeVar(

                [  $Zaehler = 1   ] ;

                ElementeAnzahl( $Tabellen.Instanzen ) // Bedingungen anpassen

              )

          ]

          Schleife (Anfang)

            

              # Anweisung einzelne Tabellen-Instanz

              Variable setzen [ $Tabellen ; Wert:

                  /* Liste der Tabellen wird aktualisiert */  

                  SetzeVar (

                    [

                      Tab = Trimme( HoleWert( $Tabellen.Instanzen; $Zaehler ) ) ;

                      Query = "

                         SELECT T.BaseTableName

                         FROM FileMaker_Tables T

                         WHERE T.TableName='" & Tab & "' " ;

                      $Table.Name = SQLAusführen ( Query ; "|" ; ¶ )

                    ];

                    Wenn(

                      MusterAnzahl( ¶ & $Tabellen & ¶ ; ¶ & $Table.Name & ¶ ) = 0 ;

                      $Tabellen & Wenn( IstLeer( $Tabellen ) = 0 ; ¶ ) &  Tab ;

                      $Tabellen

                    )

                  )

              ]

              # ENDE Anweisung einzelne Tabellen-Instanz

            

              Verlasse Schleife wenn [

                  /* Zaehler um 1 erhoehen und Abbruchbedingung ermitteln */

                  SetzeVar (

                    [ $Zaehler = $Zaehler + 1 ] ;

                    $Zaehler > $Durchlauf

                  )

              ]

          Schleife (Ende)

           

           

          Variable setzen [ $Zeit.1 ; Wert:

              /* benötigte Zeit ermitteln */

              SetzeVar (

                [

                  Stop.1 = ZeitStempel ( Hole( SystemDatum ) ; Hole( SystemUhrzeit ) )

                ];

                Stop.1 - $Start

              )

          ]

          # ENDE Tabellen-Instanzen (Liste) durchlaufen

          # ------------------------------

          • 2. Re: Langsame SQL-Abfrage
            file.maker@mybyte.ch

            Also, das ganze hat mir immer noch keine Ruhe gelassen, denn es kann ja nicht sein, dass eine solche SQL-Abfrage ganze 10 Sekunden in Anspruch nimmt. Aber nun habe ich es durch eine ganz kleine Änderung am SQL-Statement hingekriegt. Die Übung mit dem Filter-Script war für die Katz, die Lösung einfach, aber nicht ganz logisch. Vielleicht behandeln das andere DBMS anders als FileMaker. Ich würde sogar von einem leichten Bug sprechen, dessen Behebung vielleicht ein «toleranteres SQL» zulässt. Der Umfang und die Eloquenz der Fehlermeldungen in FileMaker sind im Vergleich zu anderen Systemen wie PHP gar bescheiden und erhöht den Aufwand der Fehlersuche u.U. sehr stark. Also mithin ein Argument um Programmierer von FileMaker als IDE fernzuhalten.

            Die Lösung: die Reihenfolge der Elemente. Dann geht's so wie von Anfang vorgesehen!