Announcement

Collapse
No announcement yet.

Kurioses Problem: Keine Antwort von IBServer bei SUBSELECT

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Kurioses Problem: Keine Antwort von IBServer bei SUBSELECT

    Hallo,

    ich habe folgendes Problem:

    Ich stelle über WISQL folgende Anfrage an einen Interbase 6.01 Server:

    <b><pre>SELECT *
    FROM produktion
    WHERE (produktionnr IN
    (SELECT produktionnr
    FROM rus_slots
    WHERE ((slot_nr = 100) and (slot_lizenzen > 0)) or ((slot_nr = 200) and ((slot_lizenzen < 1) or (slot_lizenzen IS NULL)))
    GROUP BY produktionnr
    HAVING (COUNT(produktionnr) = 2)))</pre></b>

    Die beiden Tabellen "Produktion" (Master) mit 22000 Datensätzen und "RUS_Slots" (Detail) mit 5 Mio Datensätzen sind über das Feld "Produktionnr" mit einander verknüpft. Zu jedem Produktionsdatensatz werden mehrere Slotdatensätze abgelegt. Die Abfrage soll mir alle Produktionsdatensätze liefern, welche in dem Slot "100" Lizenzen haben <b>und</b> im Slot "200" keine Lizenzen haben (deswegen auch GROUP BY und HAVING COUNT).

    <b>Das Ergebnis:</b>

    Der IBServer läuft ne halbe Stunde mit 100% und lieferte kein Ergebnis......zumindest habe ich den Spass nach ner halben Stunde abgebrochen, weil das kann man ja keinem Benutzer zumuten.

    <b>Der Witz:</b>

    Vorher befanden sich die beiden Tabellen in einer Paradox-Datenbank....und ich habe genau die gleiche Abfrage über die BDE gestartet (Local-SQL) und hatte nach <b>15 Sekunden</b> ein Ergebnis bei genau der gleichen Menge an Daten!!!!!

    Also was mache ich denn hier falsch.....

    <b>Anmerkung:</b>

    Das eigentlich kuriose......
    Der Interbase-Server lief auf einem 2-GHz-Rechner.....die Local-SQL-Abfrage über die BDE habe ich auf einem Pentium 200 MMX Rechner ausgeführt......

    Für schnelle Hilfe wäre ich sehr dankbar.....

    ciao Elerian...

    PS: Die Unter-Abfrage...
    <b><pre>SELECT produktionnr
    FROM rus_slots
    WHERE ((slot_nr = 100) and (slot_lizenzen > 0)) or ((slot_nr = 200) and ((slot_lizenzen < 1) or (slot_lizenzen IS NULL)))
    GROUP BY produktionnr
    HAVING (COUNT(produktionnr) = 2)</pre></b>
    ...habe ich auf dem Interbase-Server probeweise in eine Stored Procedure gepackt.....
    <b><pre>SET TERM ^;
    CREATE PROCEDURE GET_ALL_PRODUKTIONNR(MITSLOT SMALLINT, OHNESLOT SMALLINT)
    RETURNS (PRODUKTIONNR INTEGER)
    AS
    BEGIN
    FOR SELECT produktionnr
    FROM rus_slots
    WHERE ((slot_nr = :MITSLOT) and (slot_lizenzen > 0)) or ((slot_nr = :OHNESLOT) and ((slot_lizenzen < 1) or (slot_lizenzen IS NULL)))
    GROUP BY produktionnr
    HAVING (COUNT(produktionnr) = 2)
    INTO :PRODUKTIONNR
    DO
    SUSPEND;
    END^
    SET TERM ;^
    COMMIT;</pre></b>
    ....und dann eben anstelle der Unterabfrage in die eigentlich Abfrage mit aufgenommen....
    <b><pre>SELECT *
    FROM produktion
    WHERE (produktionnr IN
    (SELECT produktionnr
    FROM GET_ALL_PRODUKTIONNR(100, 200)))</pre></b>
    ...das Ergebnis war das gleiche..... <b>:-(</b>

  • #2
    ...ups, da muss ich mich wohl verzählt haben.....in der Tabelle RUS_Slots befinden dich keine 5 Mio sondern <b>nur 500 000 Datensätze</b>.......

    ciao Eleria

    Comment


    • #3
      Hallo Elerian,<BR>
      ich würde erst mal einen Subselect probeweise ausführen und den Query-Plan checken, ob der Subselect auch über Indexe läuft.<BR>
      Dann habe ich auch die Erfahrung gemacht, das ein Subselect extrem langsam ist. Du solltest den kompletten Select nach dem Where in eine Procedure verpacken, bei mir ist der Unterschied jedenfalls gewaltig.<BR>
      Gruss, Fran

      Comment


      • #4
        Also die Unterabfrage führt der Server innerhalb von 2 Sekunden aus.......<br>Im Query-Plan steht:<br>
        <pre>PLAN (S ORDER RUS_SLOTS0)</pre><br>
        Folglich verwendet die Abfrage keine Indizes.<br>
        Wie kann ich denn in der SELECT Anweisung angeben, dass Indizes verwendet werden sollen??

        Der PrimärIndex liegt auf der Produktionnr-Spalte und es existieren Indizes auf die anderen beiden Spalten (Slot_nr und Slot_Lizenzen).

        ciao Elerian

        Comment


        • #5
          versuch doch mal einen zusammengesetzten Index auf produktionnr,slot_nr,slot_lizenzen.<BR>oder eine procedure...<BR>
          CREATE PROCEDURE IS_PRODUKT (<BR>
          nr INTEGER)<BR>
          RETURNS (OK CHAR(1))<BR>
          AS<BR>
          DECLARE VARIABLE anz1 integer;<BR>
          DECLARE VARIABLE anz2 integer;<BR>
          begin<BR>
          OK = 'N';<BR>
          SELECT count(produktionnr) FROM rus_slots WHERE <BR>
          ((produktionnr = :nr) and ((slot_nr = 100) and (slot_lizenzen > 0))<BR>
          into :anz1<BR>
          SELECT count(produktionnr) FROM rus_slots WHERE <BR>
          ((produktionnr = :nr) and ((slot_lizenzen < 1) or (slot_lizenzen IS NULL))
          into :anz2<BR>
          if ((anz1>0) and (anz2>0) then OK = 'J'<BR>
          suspend;<BR>
          end<BR>
          und dann den Subselect: where (select ok from IS_PRODUKT(produktion.produktionnr))='J'<BR>
          Konnte jetzt natürlich keinen SystaxCheck machen,<BR>
          viel Erfolg<BR>
          Fran

          Comment

          Working...
          X