Mysql
 sql >> Datenbank >  >> RDS >> Mysql

MySQL:zusammengesetzter Index Volltext+btree?

Verwenden Sie IN BOOLEAN MODE .

Der Datumsindex ist nicht sinnvoll. Es gibt keine Möglichkeit, die beiden Indizes zu kombinieren.

Achtung, wenn ein Benutzer nach etwas sucht, das in 30.000 Zeilen auftaucht, wird die Abfrage langsam sein. Es gibt keinen direkten Weg drumherum.

Ich vermute, Sie haben einen TEXT Spalte in der Tabelle? Wenn ja, gibt es Hoffnung. Anstatt blind SELECT * auszuführen , lassen Sie uns zuerst die IDs finden und das LIMIT abrufen angewendet, dann mach den * .

SELECT a.* 
    FROM tbl AS a
    JOIN ( SELECT date, id
             FROM tbl
             WHERE MATCH(...) AGAINST (...)
             ORDER BY date DESC
             LIMIT 10 ) AS x
        USING(date, id)
    ORDER BY date DESC;

Zusammen mit

PRIMARY KEY(date, id),
INDEX(id),
FULLTEXT(...)

Diese Formulierung und Indizierung sollte wie folgt funktionieren:

  1. Verwenden Sie FULLTEXT Um 30.000 Zeilen zu finden, geben Sie das PK ein.
  2. Sortieren Sie mit dem PK 30.000 Zeilen nach date .
  3. Wählen Sie die letzten 10 aus und liefern Sie date, id
  4. Greife mit dem PK 10 Mal zurück in die Tabelle.
  5. Erneut sortieren. (Ja, das ist notwendig.)

Mehr (Antwort auf eine Fülle von Kommentaren):

Das Ziel hinter meiner Neuformulierung ist es, zu vermeiden, dass alle abgerufen werden Spalten von 30K Reihen. Stattdessen wird nur der PRIMARY KEY abgerufen , reduziert das dann auf 10 und ruft dann * ab nur 10 Reihen. Es wurde viel weniger Zeug herumgeschaufelt.

Bezüglich COUNT auf einer InnoDB-Tabelle:

  • INDEX(col) macht daraus einen index Scan funktioniert für SELECT COUNT(*) oder SELECT COUNT(col) ohne WHERE .
  • Ohne INDEX(col), SELECT COUNT(*)will use the "smallest" index; but SELECT COUNT(col)` benötigt eine Tabelle scannen.
  • Ein Tabellenscan ist normalerweise langsamer als ein Index-Scan.
  • Achten Sie auf das Timing – es wird erheblich davon beeinflusst, ob der Index und/oder die Tabelle bereits im RAM zwischengespeichert ist.

Noch was zu FULLTEXT ist der + vor Wörtern - um zu sagen, dass jedes Wort existieren muss, sonst gibt es keine Übereinstimmung. Dadurch können die 30.000 eingespart werden.

Der FULLTEXT index liefert das date, id ist zufällige Reihenfolge, nicht PK-Reihenfolge. Wie auch immer, es ist 'falsch', irgendeine Reihenfolge anzunehmen, daher ist es 'richtig', ORDER BY hinzuzufügen , und lassen Sie ihn dann vom Optimierer verwerfen, wenn er es weiß dass es überflüssig ist. Und manchmal kann der Optimierer den Vorteil von ORDER BY nutzen (nicht in Ihrem Fall).

Entfernen Sie nur den ORDER BY , führt in vielen Fällen dazu, dass eine Abfrage viel schneller ausgeführt wird. Dies liegt daran, dass das Abrufen von beispielsweise 30.000 Zeilen und deren Sortierung vermieden wird. Stattdessen liefert es einfach "beliebige" 10 Zeilen.

(Ich habe keine Erfahrung mit Postgres, daher kann ich diese Frage nicht beantworten.)