Peter: WHERE col = 1 OR col = 2 OR col = 3 oder WHERE COL in (1,2,3)?

Tach auch,

mal ne Frage zur Effizienz einer SELECT-Abfrage in MySQL (aus PHP, aber das sollte eigentlich egal sein):

Abhängig von den selektierten Options von einem HTML-Select-Tag (mit multiple-Eigenschaft) sollen die Datensätze aus der Datenbank geholt werden, deren Spalte x mit einem der Werte (lauter Zahlen) aus den gewählten Options übereinstimmt.

In der überwiegenden Zahl der Fälle wird vermutlich nur eine einzige Option ausgewählt werden.

Die gewählten Werte hab ich ja als Array, bisher generiere ich damit einfach die WHERE-Bedingung:

$sql .= ' AND col IN ('.implode(",", $POST['myselect']).') ';

Das wird an sowieso vorhandene Bedingungen einfach noch hintendran gehängt.

Im Normalfall (nur eine Option selektiert) ergibt sich damit also
' AND col IN (17)'

Effektiv ist das - es werden nur die gewünschten Datensätze ausgewählt.
Jetzt frage ich mich, ob es nicht effizienter wäre, bei nur einer selektierten Option den Code
' AND col = 17'
generieren zu lassen.
Vielleicht auch noch bei zwei ausgewählten Werten
' AND ((col = 17) OR (col = 42))'

statt ' AND col IN (17,42)'

Kann mir jemand sagen, ob das einen Effizienzgewinn bringt? Oder ist der so gering, daß er durch den (minimal) aufwendigeren PHP-Code wieder aufgefressen?

Muchachos Garcia!

Peter B.

  1. yo,

    $sql .= ' AND col IN ('.implode(",", $POST['myselect']).') ';

    tipp am rande, nicht ungeprüft daten in deine abfrage oder generell code einbauen.

    Kann mir jemand sagen, ob das einen Effizienzgewinn bringt? Oder ist der so gering, daß er durch den (minimal) aufwendigeren PHP-Code wieder aufgefressen?

    der PHP code sollte in aller regel nicht so viel zusätzliche zeit in anspruch nehmen, der gewinn dadurch kann aber unter umständen erheblich bis enorm sein. es spielt durch aus eine wichtige rolle, wie man die sql abfrage stellt, auch wenn das ergebnis das gleiche ist.

    aber wenn du nicht schon auf geschwidigkeitsprobleme gestossen bist, würde ich eine andere regel auch nicht aus den augen verlieren, keep it simple (kis). mit anderen worten wenn nicht anders nötig, mach den code so einfach wie möglich.

    Ilja

    1. Hi,

      <zitat source="Albert Einstein">
      Keep it simple, as simple as possible. But no simpler.
      </zitat>

      In diesem Sinne.

      Frank

    2. Tach,

      $sql .= ' AND col IN ('.implode(",", $POST['myselect']).') ';
      tipp am rande, nicht ungeprüft daten in deine abfrage oder generell code einbauen.

      Schon klar, ich hab den Code hier aufs wesentliche reduziert - daß geprüft wird, daß nur Zahlen im Array stehen, ist klar.

      Kann mir jemand sagen, ob das einen Effizienzgewinn bringt? Oder ist der so gering, daß er durch den (minimal) aufwendigeren PHP-Code wieder aufgefressen?
      der PHP code sollte in aller regel nicht so viel zusätzliche zeit in anspruch nehmen, der gewinn dadurch kann aber unter umständen erheblich bis enorm sein. es spielt durch aus eine wichtige rolle, wie man die sql abfrage stellt, auch wenn das ergebnis das gleiche ist.

      Naja, genau deswegen frage ich ja, welche Variante für wenige Werte effizienter ist.

      aber wenn du nicht schon auf geschwidigkeitsprobleme gestossen bist, würde ich eine andere regel auch nicht aus den augen verlieren,

      Das Problem ist: hier in der Testumgebung hab ich nur ca. 50000 Datensätze. In der Umgebung, in der das irgendwann laufen soll, werden es wohl recht bald ein paar Millionen werden.

      Peter B.

      1. yo,

        ich dachte, deine frage war, ob es sich unter php lohnt, die query zu "tunen". und die antwort darauf wäre ja, wenn es zu geschwindigkeitsproblemen kommt. wie genau das tuning aussieht, ist leider nicht so pauschal zu beantworten. es kommt darauf an, welches dbms du benutzt, welche version, ob du über mehrere tabellen gehst, welche indizies du hast, etc. auch ist viel trial on error angesagt, sprich testen, wie das dbms auf welche "schreibweise" der query reagiert. das ist nicht immer so eindeutig vorrauszusagen.

        Das Problem ist: hier in der Testumgebung hab ich nur ca. 50000 Datensätze. In der Umgebung, in der das irgendwann laufen soll, werden es wohl recht bald ein paar Millionen werden.

        wenn du aus einer tabelle von ein paar millionen datensätze nur einige hundert selektierst und einen entsprechenden index besitzt, dann sollte das kein wirkliches problem sein. problematisch können zum beispiel joines über mehrere tabellen oder fullscans bei großen tabellen sein.

        Ilja

        1. yo,

          habe noch vergessen zu erwähnen, dass du deine testumgebung an die menge der datensätze in life betrieb angleichen solltest. das geht recht schnell mit verdoppellungen ala INSERT INTO ....SELECT

          Ilja

  2. hi,

    Im Normalfall (nur eine Option selektiert) ergibt sich damit also
    ' AND col IN (17)'

    Jetzt frage ich mich, ob es nicht effizienter wäre, bei nur einer selektierten Option den Code
    ' AND col = 17'
    generieren zu lassen.
    Vielleicht auch noch bei zwei ausgewählten Werten
    ' AND ((col = 17) OR (col = 42))'

    statt ' AND col IN (17,42)'

    ich glaube kaum, dass sich das irgendwie bemerkbar auswirken wird, egal bei welcher datenmenge.

    mysql optimiert selber einiges bei WHERE-klauseln, und die doku sagt selber, dass dort bisher nur ein teil dokumentiert ist.

    aber wenn ich mir dort nur das erste beispiel anschaue, bzgl. des entfernens unnötiger klammern - dann gehe ich davon aus, dass mysql deine bedingung sowieso erst mal "zerlegt", und dass IN() oder mehrere = mit OR verknüpft keinen unterschied beim "raussuchen" der datensätze machen; es wird für mysql allenfalls beim parsen deiner query einen unterschied machen, aber auch der dürfte absolut zu vernachlässigen sein.

    dass du mysql beim anschließenden suchen der daten "hilfst", in dem du einen geeigneten index erstellst, scheint mir weitaus wichtiger.

    gruß,
    wahsaga

    --
    /voodoo.css:
    #GeorgeWBush { position:absolute; bottom:-6ft; }
    1. Tach,

      ich glaube kaum,

      Leider auch nur Glaube ... ;-)

      mysql optimiert selber einiges bei WHERE-klauseln, und die doku sagt selber, dass dort bisher nur ein teil dokumentiert ist.

      Naja, zu IN () steht nichts dort.

      aber wenn ich mir dort nur das erste beispiel anschaue, bzgl. des entfernens unnötiger klammern - dann gehe ich davon aus, dass mysql deine bedingung sowieso erst mal "zerlegt", und dass IN() oder mehrere = mit OR verknüpft keinen unterschied beim "raussuchen" der datensätze machen; es wird für mysql allenfalls beim parsen deiner query einen unterschied machen, aber auch der dürfte absolut zu vernachlässigen sein.

      Daß das Parsen das geringere Problem ist, sehe ich auch so - es geschieht ja pro Query nur einmal, egal wieviel Millionen Datensätze nachher durchsucht werden müssen.

      dass du mysql beim anschließenden suchen der daten "hilfst", in dem du einen geeigneten index erstellst, scheint mir weitaus wichtiger.

      Die betroffenen Spalten, um die es hier geht, sind sowieso Index-Spalten.

      Peter B.