RAND() optimieren

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • RAND() optimieren

    Hallo,

    ich bin dabei, meine Datenbanken etwas zu optimieren und habe spasseshalber mal 100.000 Daetnsätze erzeugt. Der Schreck sitzt mir immernoch in den Knochen ...

    Nun, ich bin allerdings soweit, dass die meisten Abfragen recht flux über die Bühne gehen, bis auf 2.

    Es handelt sich um eine Artikeldatenbank, die ich, wegen Mehrsprachigkeit, aufgespalten habe.

    Zum einen die Artikelinformationen:

    wichtige Felder für die Abfrage sind:
    id = PRIMARY
    aktiv, frontpage, anzeigen (sind in einem Index)
    (100.000 Datensätze)

    zum anderen der Artikeltext:
    id = PRIMARY
    artid = Index - entspricht der ID aus den Artikelinformationen
    sprachid = Index mit artid
    artikelkeywords = ein eigener FULLTEXT Index
    (200.00 Datensätze, einmal sprachid='0' und sprachid='1')

    Spielt hier aber keine Rolle, da ich alle Abfragen getrennt mache.

    zum ersten Problem:
    ich möchte auf der Startseite 10 zufällige Artikel anzeigen, die aktiv sind, das Kennzeichen frontpage auf "on" haben und angezeigt werden sollen - anzeigen="on"

    Mein Query:
    Code:
    SELECT id FROM artikelinfo WHERE aktiv="Y" AND frontpage="on" AND anzeigen="on" ORDER BY RAND() LIMIT 10
    Es sind ca. die Hälfte mit frontpage="on".
    Diese Abfrage dauert ca. 4 Sekunden une hält natürlich auf.
    Ich vermute, es liegt am RAND(), lass ich das weg, ist das Ergebnis sofort da.

    Das zweite Problem ist natürlich die Suche nach bestimmten Worten aus der Artikelbezeichnung. Diese habe ich nun schon soweit optimiert, dass ich hier ein eigenes Feld "artkey" geschaffen habe. Hier sind alle Worte der Artikelbezeichnung in kleinbuchstaben und nur einmalig vorhanden (der, die, das und sowas garnicht).

    Allerdings ist diese Abfrage natürlich katastrophal:
    Code:
    SELECT artid FROM artikeltext WHERE sprachid='0' AND artkey LIKE '%[suchwort]%'
    Ob der Artikel aktiv ist oder nicht, würde ich in einer 2. Abfrage herausfinden, stellt aber nicht das Problem dar.
    Die Abfrage dauert an sich schon 5 Minuten

    Für ein paar Ideen oder Lösungsansätze wäre ich echt dankbar.

    Gruß + Danke
    Marco

  • #2
    Re: RAND() optimieren

    Original geschrieben von whyte
    Code:
    SELECT id FROM artikelinfo WHERE aktiv="Y" AND frontpage="on" AND anzeigen="on" ORDER BY RAND() LIMIT 10
    Es sind ca. die Hälfte mit frontpage="on".
    Diese Abfrage dauert ca. 4 Sekunden une hält natürlich auf.
    Ich vermute, es liegt am RAND(), lass ich das weg, ist das Ergebnis sofort da.
    du sortierst nach einer zufälligen zahl .. dabei wünscht mysql dort ein DB-FELD
    ich würde mittels php mir die letzte mögliche ID ausgeben lassen die das kriterium erfüllen (frontpage, anzeigen, aktiv)
    dann mittels:
    [/QUOTE]
    PHP-Code:
    rand(1,$letzte_id); 
    - mir eine zufällige zahl generieren lassen
    - überprüfen ob dieser datensatz zulässig ist (frontpage, anzeigen, aktiv)
    - das 9 mal wiederholen .. so hast du deine 10 datensätze.

    [QUOTE]Original geschrieben von whyte
    Code:
    SELECT artid FROM artikeltext WHERE sprachid='0' AND artkey LIKE '%[suchwort]%'
    da werden jetzt 100000 datensätze durchgeguckt ob diese SUCHWORT drinne haben .. kein wunder das dieses 5 minuten dauert
    Gruß
    Uzu

    private Homepage

    Kommentar


    • #3
      Ok, danke
      für den ersten Teil hab ich jetzt einen Anhaltspunkt, ich denke, das bringt wirklich was.
      Einfach eine Schleife mit Zufallszahlen und SQL checken lassen, ob dieser Datensatz dann gültig ist. Dies 10 mal machen und dann erst weiter.
      Müsste ich mal testen, ob das dann schneller ist, muss ja auch Duplikate auschliessen.

      Aber für den 2. Teil, das ist schon schwerer. Ich muss mir mal ansehen, wie das grosse Foren machen mit der Suche, ist ja eigentlich der selbe Vorgang.

      Gruß
      marco

      Kommentar


      • #4
        @UzumakiNaruto: Verstehe ich das richtig, dass du empfiehlst (mindestens) 10 Queries abzusetzen?

        Die RAND-Problematik ist aber eigentlich bekannt. (Dass es bei 100.000 Datensätzen schon probleme gibt, hätte ich allerdings nicht gedacht.) Jedenfalls gibt es dazu schon Workarounds, die es nur noch zu finden gilt.

        Aber für den 2. Teil, das ist schon schwerer. Ich muss mir mal ansehen, wie das grosse Foren machen mit der Suche, ist ja eigentlich der selbe Vorgang.
        Die nutzen die Volltextsuche von MySQL oder Indizieren die Texte. Jedenfalls wird auf ein LIKE mit sicherheit verzichtet.

        Kommentar


        • #5
          Original geschrieben von TobiaZ
          @UzumakiNaruto: Verstehe ich das richtig, dass du empfiehlst (mindestens) 10 Queries abzusetzen?

          Die RAND-Problematik ist aber eigentlich bekannt. (Dass es bei 100.000 Datensätzen schon probleme gibt, hätte ich allerdings nicht gedacht.) Jedenfalls gibt es dazu schon Workarounds, die es nur noch zu finden gilt.

          Die nutzen die Volltextsuche von MySQL oder Indizieren die Texte. Jedenfalls wird auf ein LIKE mit sicherheit verzichtet.
          so wäre jetzt meine herangehensweise gewesen. aber ich habe eben mal schnell ne suchmaschine benutzt .. und die nannte mir genau das, was der TS schon gemacht hat.

          Bei MySQL ist so ein Ergebnis einfach zu erzielen.

          Der Befehl ORDER BY bekommt als weitere Angabe üblicherweise eine oder mehrere Spalten mitbekommt, die die Sortierung bestimmen. Der Befehl akzeptiert an dieser Stelle aber auch die Funktion RAND(). Drei zufällige ausgewählte Artikel aus einer Tabelle "news" fördert beispielsweise folgendes Kommando zutage:


          SELECT * FROM news ORDER BY RAND() LIMIT 3

          Bei Tabellen mit sehr vielen Datensätzen ist diese Methode allerdings aufwändig, da MySQL für jeden Datensatz ein eigene Zufallszahl erzeugen muss.
          Gruß
          Uzu

          private Homepage

          Kommentar


          • #6
            Habe auch mal ne Suchmaschine benutzt. Erstes Ergebnis: http://jan.kneschke.de/projects/mysql/order-by-rand

            Kommentar


            • #7
              Mensch den Artikel wollte ich auch gerade posten, das ist schon länger einer meiner Lieblingartikel zu SQL-Optimierung
              signed oder unsigned... das ist hier die Frage

              Kommentar


              • #8
                Hallo,

                vielen Dank, den Beitrag werd ich mir mal zu genüte führen und versuchen zu verstehen, denn ich erkenne am Schluss nur noch einen Kilometer langen Befehl den ich bis jetzt noch nicht verstanden habe.

                Die 10 Querys hatte ich nach einigem Überlegen aber wieder verworfen, denn es könnte auch die Situation auftreten, dass ich tatsächlich nur 10 Artikel mit dem frontpage="on" habe, dann würde die Suche wohl ins unendliche laufen ...

                Danke

                EDIT: ich raff das glaub ich nicht, ich kann da keinen Befehl erkennen, den ich auf anwenden könnte.
                Zuletzt geändert von whyte; 16.06.2008, 19:39.

                Kommentar


                • #9
                  :-)

                  Code:
                  SELECT id FROM shop_artikel AS r1 JOIN (SELECT (RAND() * (SELECT MAX(id) FROM shop_artikel)) AS id2) AS r2 WHERE r1.id >= r2.id2 AND aktiv='on' AND frontpage='on' ORDER BY r1.id ASC LIMIT 10;
                  bringt mir:

                  Code:
                  +--------+
                  | id     |
                  +--------+
                  | 100000 |
                  | 100001 |
                  | 100002 |
                  | 100003 |
                  | 100008 |
                  | 100011 |
                  | 100012 |
                  | 100016 |
                  | 100020 |
                  | 100022 |
                  +--------+
                  10 rows in set (0.16 sec)
                  Die Zeit ist gut, nur kommt zu 98% immer genau diese Ausgabe.

                  ich glaub, ich hab das immer noch nicht kapiert ...
                  Zuletzt geändert von whyte; 16.06.2008, 20:04.

                  Kommentar

                  Lädt...
                  X