Hier sind einige Dinge, die ich versuchen würde, in der Reihenfolge der zunehmenden Schwierigkeit:
(einfacher) - Stellen Sie sicher, haben Sie das Recht Abdeckung Index
CREATE INDEX ix_temp ON relations (relation_title, object_title);
Dies sollte die Leistung für Ihr vorhandenes Schema maximieren, da (solange Ihre Version des mySQL-Optimierers nicht wirklich dumm ist!) Es die Anzahl der benötigten E/As minimiert, um Ihre Anfrage zu erfüllen (anders als wenn der Index in der umgekehrten Reihenfolge steht) Index muss gescannt werden) und deckt die Abfrage ab, sodass Sie den Clustered Index nicht berühren müssen.
(ein wenig härter) - stellen Sie sicher, dass Ihre varchar Felder so klein sind möglich
Einer der perf Herausforderungen mit varchar Indizes für MySQL ist, dass bei der Verarbeitung einer Abfrage, die vollständig erklärt Größe der Feld wird in RAM gezogen werden. Wenn Sie also varchar (256) verwenden, aber nur 4 Zeichen verwenden, zahlen Sie immer noch die 256-Byte-RAM-Auslastung, während die Abfrage verarbeitet wird. Autsch! Wenn Sie Ihre Varchar-Limits einfach reduzieren können, sollte dies Ihre Abfragen beschleunigen.
(härter) - Normalisieren
30% Ihrer Zeilen einen einzelnen String-Wert ist ein klarer Schrei in einer anderen Tabelle zu normalisieren, so dass Sie keine Strings Millionen mal zu duplizieren. Ziehen Sie in Betracht, in drei Tabellen zu normalisieren und ganzzahlige IDs zu verwenden, um sie zu verbinden.
In einigen Fällen können Sie unter den Abdeckungen normalisieren und die Normalisierung mit Ansichten ausblenden, die mit dem Namen der aktuellen Tabelle übereinstimmen ... dann müssen Sie nur Ihre INSERT/UPDATE/DELETE-Abfragen auf die Normalisierung aufmerksam machen, können aber Lassen Sie Ihre SELECTs in Ruhe.
(am härtesten) - Hash der Zeichenfolge Spalten und Index die Hashes
Wenn Mittel Normalisierung zu viel Code zu ändern, aber Sie können das Schema ein wenig ändern, können Sie 128-Bit-Hash-Werte zu prüfen, die Schaffung für Ihre String-Spalten (mit der MD5 function). In diesem Fall müssen Sie (anders als bei der Normalisierung) nicht alle Ihre Abfragen ändern, nur die INSERTs und einige der SELECTs. Wie auch immer, Sie wollen Ihre String-Felder hashen und dann einen Index für die Hashes erstellen, z.
CREATE INDEX ix_temp ON relations (relation_title_hash, object_title_hash);
Beachten Sie, dass Sie benötigen, um mit der SELECT zu spielen, um sicherzustellen, dass Sie die Berechnung über den Hash-Index tun, und nicht in der Clustered-Index (erforderlich Ziehen des aktuellen Textwert von object_title zu lösen, um um die Anfrage zu erfüllen).
Wenn relation_title eine kleine varchar-Größe hat, aber der Objekttitel eine lange Größe hat, können Sie möglicherweise nur object_title hashen und den Index auf (relation_title, object_title_hash)
erstellen.
Beachten Sie, dass diese Lösung nur hilft, wenn eines oder beide dieser Felder im Verhältnis zur Größe der Hashes sehr lang ist.
Beachten Sie auch, dass es beim Hashing interessante Auswirkungen auf die Groß- und Kleinschreibung/Kollation gibt, da der Hash eines Kleinbuchstaben-Strings nicht mit dem Hash eines Großbuchstabens übereinstimmt. Sie müssen also sicherstellen, dass Sie die Kanonisierung auf die Strings anwenden, bevor Sie sie hash- en - in anderen Worten, nur Kleinbuchstaben, wenn Sie in einer Groß-/Kleinschreibung zwischen Groß- und Kleinschreibung unterscheiden. Je nachdem, wie Ihre DB führende/nachstehende Leerzeichen behandelt, möchten Sie möglicherweise auch Leerzeichen am Anfang oder Ende beschneiden.
Könnten Sie bitte weitere Details z. die ganze Auswahl und die Tabellenstruktur? Noch ein erster Versuch: Verwenden Sie richtig Indizes? – Kosi2801
Ich habe unten ein paar mögliche Lösungen hinzugefügt, aber ich stimme Kosi zu, dass die Definition der Tabellen (insbesondere die Länge der Varchar-Spalten!) Und die Index-Definitionen sehr hilfreich wären, um dies zu diagnostizieren. –
Sind Beziehungen eine Innodb- oder MyISAM-Tabelle? –