2016-03-20 9 views
6

Ich schreibe eine Abfrage, um Spielerverbote aus einer anderen Tabelle auszuwählen, aber erstens dauert es sehr langsam 7-14 Sekunden und zweitens gibt es ungültige Zeilen zurück.MySQL Query gibt ungültige Zeilen zurück und sehr langsam

Die erste Abfrage lautet wie folgt:

SELECT * 
FROM sourcebans.sb_bans 
WHERE removetype IS NULL 
     AND removedon IS NULL 
     AND reason NOT LIKE '%[FragSleuth] Duplicate account%' 
     AND ip IN(SELECT DISTINCT ip 
       FROM fragsleuth.history 
       WHERE trackingid = "ad000c3803b48190aabf382e01b957c9") 
     OR authid IN(SELECT DISTINCT steamid 
        FROM fragsleuth.history 
        WHERE trackingid = "ad000c3803b48190aabf382e01b957c9") 

Die zweite Abfrage ist als

folgt
SELECT * FROM `history` WHERE trackingid = "ad000c3803b48190aabf382e01b957c9" 

Und ein paar Screenshots zu zeigen, was ich meine: First QuerySecond Query

In screenshot 1 Sie können sehen, dass es eine Zeile zurückgibt, wo der removedon und removeType nicht null ist, wenn ich gefragt habe Abfrage, um nur Zeilen mit NULL zurückzugeben.

Ich habe auch Angst, dass in der History-Tabelle doppelte Einträge für die Spalten steamid und ip, die die Abfrage verlangsamen könnte, gibt es eine Möglichkeit, die Abfrage nur Zeilen mit einer eindeutigen IP oder Steamid basieren auf die Tracking-ID?

Jede Hilfe würde sehr geschätzt werden.

Dank

Edit: Ich mit Hilfe überwältigt bin, Dank @maraca, @Skorpioh und @ Adam Silenko, ist die Abfragezeit jetzt weniger als eine Sekunde!

+1

Und Sie brauchen wahrscheinlich ein '(' before 'ip' und ein' '' '' am Ende. – maraca

Antwort

1

Die Abfrage gibt Zeilen, die nicht NULL sind, weil es als
(... AND ... AND ...) OR ... statt
... AND ... AND (... OR ...)

Sie eine Zahnspange So interpretiert hinzufügen müssen, auch die DISTINCT ist nicht erforderlich:

SELECT * 
FROM sourcebans.sb_bans 
WHERE removetype IS NULL 
     AND removedon IS NULL 
     AND reason NOT LIKE '%[FragSleuth] Duplicate account%' 
     AND (ip IN(SELECT ip 
       FROM fragsleuth.history 
       WHERE trackingid = "ad000c3803b48190aabf382e01b957c9") 
     OR authid IN(SELECT steamid 
        FROM fragsleuth.history 
        WHERE trackingid = "ad000c3803b48190aabf382e01b957c9")) 
+0

Danke, das hat es behoben! Aber gibt es jetzt eine Möglichkeit, die Abfrage schneller zu machen? – SM9

+0

@ SM9 Gern geschehen. Sie können die Abfrage analysieren und die wichtigen Spalten indizieren. Oder wenn Sie das nicht können, können Sie versuchen, die Bedingungen in denen zu ändern, manchmal hilft es. – maraca

+0

@ SM9. . . Sie können eine andere Frage stellen, um die Abfrage schneller zu machen. –

2

die und haben dann eine höhere Priorität oder ... Sie müssen auf Ihre Tabellen indexieren np. add index zum trackingid-Feld in fragsleuth.history, wenn Sie nicht haben

Sie können wahrscheinlich schneller mit einer Unterabfrage tun, aber ich bin mir nicht sicher.

SELECT * 
FROM sourcebans.sb_bans 
WHERE removetype IS NULL 
AND removedon IS NULL 
AND reason NOT LIKE '%[FragSleuth] Duplicate account%' 
AND exists (
    SELECT 1 from fragsleuth.history 
    WHERE trackingid = "ad000c3803b48190aabf382e01b957c9" 
    and (ip = sourcebans.ip or steamid = sourcebans.authid)) 
+0

Hallo, kannst du erklären, was das Hinzufügen eines Indexes zur Trackingid tut? Danke – SM9

+0

Wenn Tabelle Geschichte ist groß (wahrscheinlich ja) und Sie haben Bedingung für Spalte Trackingid in Unterabfrage, Index auf diesem Feld kann Suche Zeilen für diese Unterabfrage verbessern –

+0

Ah ok, ich tat dies und seine sehr schnell jetzt, danke. – SM9

1

Sie haben eine operatior precendence Problem hier und das ist, warum es endet Ergebnisse mit denen removetype/removedon nicht null ist.

Wenn Sie http://dev.mysql.com/doc/refman/5.7/en/operator-precedence.html überprüfen, sehen Sie, dass AND eine höhere Priorität als OR hat, was bedeutet, dass Ihre Abfrage alle Prädikate zusammen mit dem Operator "AND" ausführt und erst danach OR ein Spiel und der Rest spielt keine Rolle mehr.

Wenn ich nicht falsch liege die unten sollte korrekt funktionieren:

SELECT * 
FROM sourcebans.sb_bans 
WHERE removetype IS NULL 
     AND removedon IS NULL 
     AND reason NOT LIKE '%[FragSleuth] Duplicate account%' 
     AND 
      (
       ip IN (SELECT DISTINCT ip 
         FROM fragsleuth.history 
         WHERE trackingid = "ad000c3803b48190aabf382e01b957c9") 
       OR 
       authid IN(SELECT DISTINCT steamid 
          FROM fragsleuth.history 
          WHERE trackingid = "ad000c3803b48190aabf382e01b957c9") 
      ) 

Im Hinblick auf Verbesserungen in der Geschwindigkeit, sollten Sie zunächst einen abdeckenden Index für die removetype, removedon, ip und authid Spalten erstellen. Dies wird helfen, aber wahrscheinlich nicht genug, da die LIKE-Operation sehr teuer ist.

Das letzte, was Sie tun sollten, ist zu überprüfen, ob Sie

Grund NOT LIKE ändern kann '% [FragSleuth] Konto% Duplizieren'

in noch etwas anderes. Kannst du zum Beispiel das führende% eliminieren, damit es zumindest eine viel schnellere Übereinstimmung bringt? Hängt natürlich davon ab, was genau diese Spalten speichern.

+0

Danke! das funktioniert genauso wie die erste Antwort;) – SM9

+0

Der Grund ist wie folgt angehängt: \ "[FragSleuth] Doppelter Account (Name:% s) (AuthId:% s) (Grund:% s) \" "Also bin ich nicht Sicher, ob es einen besseren Weg gibt. – SM9

+0

Wenn die Gründe, die du ALWAYS filtern willst, mit "[FragSleuth] Duplicate account" beginnen, kannst du das sehr verbessern, indem du es in "Grund NOT LIKE '[FragSleuth] Duplicate account%' änderst" (Beachten Sie, dass die führende% gelöscht wird. Dies wird die LIKE-Operation viel beschleunigen. – Skorpioh