2016-03-20 17 views
6

Sto scrivendo una query per selezionare divieti giocatore da un'altra tabella, ma in primo luogo il suo prendere molto lentamente circa 7-14 secondi e in secondo luogo le sue righe non valide di ritorno.Query MySQL che restituisce righe non valide e molto lenta

La prima domanda è la seguente:

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") 

La seconda query è la seguente

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

E un paio di screenshot per mostrare cosa intendo: First QuerySecond Query

In screenshot 1 puoi vedere che restituisce una riga in cui rimossi e removetype non sono nulli quando ho chiesto al eseguire una query per restituire solo le righe con NULL.

Ho anche paura che all'interno della tabella della cronologia ci saranno voci duplicate per le colonne steamid e ip che potrebbero rallentare la query, esiste un modo per fare in modo che la query selezioni solo le righe con un IP o steamid univoco basato su il trackingid?

Qualsiasi aiuto sarebbe molto apprezzato.

Grazie

Edit: Sono sopraffatto con l'aiuto, Grazie a @maraca, @Skorpioh e @ Adamo Silenko, il tempo di query è ora meno di un secondo!

+1

E probabilmente è necessario un '(' prima 'ip' e a') 'alla fine. – maraca

risposta

1

La query restituisce righe che non NULL sono perché viene interpretato come
(... AND ... AND ...) OR ... invece di
... AND ... AND (... OR ...)

Quindi è necessario aggiungere le parentesi graffe, anche il DISTINCT non è necessaria:

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

Grazie, l'ha risolto! Ma ora c'è un modo per rendere la query più veloce? – SM9

+0

@ SM9 Prego. È possibile analizzare la query e indicizzare le colonne importanti. O se non puoi farlo puoi provare a riordinare le condizioni in cui, a volte aiuta. – maraca

+0

@ SM9. . . Puoi fare un'altra domanda su come rendere la query più veloce. –

2

la e avere una priorità più alta allora o ... Hai bisogno di indicizzare sui tuoi tavoli np. aggiungi l'indice al campo trackingid in fragsleuth.history se non disponi di

Probabilmente puoi fare più velocemente utilizzando una query secondaria, ma non sono sicuro.

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

Ciao, puoi spiegare cosa aggiungerebbe un indice sul trackingid? Grazie – SM9

+0

se la cronologia di una tabella è grande (probabilmente sì) e hai una condizione sulla colonna trackingid in sottoquery, l'indice su questo campo può migliorare la ricerca di righe per questa subquery –

+0

Ah ok, l'ho fatto ed è molto veloce ora, grazie. – SM9

1

avete un problema precendenza operatior qui e è per questo che finisce per avere i risultati in cui removetype/removedon non è nullo.

Se si controlla http://dev.mysql.com/doc/refman/5.7/en/operator-precedence.html, si vedrà che AND ha priorità più alta di OR, ovvero che la query eseguirà tutti i predicati incollati insieme con l'operatore "AND" e solo dopo eseguirà l'operazione OR, ovvero i risultati verranno visualizzati dove è presente l'authorid una partita e il resto non ha più importanza.

Se non sbaglio il seguito dovrebbe funzionare correttamente:

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") 
      ) 

Per quanto riguarda miglioramenti di velocità, è necessario creare un indice di copertura per le colonne removetype, removedon, ip e authid prima. Ciò aiuterà ma probabilmente non sarà sufficiente in quanto l'operazione LIKE è molto costosa.

L'ultima cosa da fare è quello di verificare se è possibile modificare

ragione NOT LIKE '% [FragSleuth] Duplica account%'

in qualcos'altro. Puoi ad esempio eliminare la percentuale iniziale in modo che possa almeno fare una corrispondenza molto più veloce? Dipende ovviamente da cosa esattamente memorizzano quelle colonne.

+0

Grazie! questo funziona come la prima risposta;) – SM9

+0

Il motivo viene aggiunto in questo modo: \ "[FragSleuth] Account duplicato (Nome:% s) (AuthId:% s) (Motivo:% s) \" "Quindi non lo sono Se c'è un modo migliore, – SM9

+0

Se i motivi per cui vuoi filtrare SEMPRE iniziano con "[FragSleuth] Account duplicato", puoi migliorarlo molto cambiandolo in "ragione NON MI PIACE" [FragSleuth] Account duplicato% "" (si noti che la percentuale iniziale è stata cancellata) Ciò velocizzerà molto l'operazione LIKE – Skorpioh

Problemi correlati