Domanda

Sto cercando di trovare un modo semplice per migliorare le prestazioni per forum molto attivi dove ci sono un numero enorme di post e mysql non può più fare il tipo di tabella in memoria e non sembra sfruttare appieno gli indici. < / P >.

Questa semplice query trova il post più recente in ogni argomento per un utente per determinare se hanno risposte poiché (successivamente, confrontando più avanti l'argomento)

SELECT p.*, MAX(post_time) as post_time FROM forum_posts AS p   
WHERE p.poster_id = '1' AND p.post_status = '0' 
GROUP BY p.topic_id  
ORDER BY post_time DESC 
LIMIT 50
.

Semplice, tavolo piatto sembra qualcosa di simile a

post_id | poster_id | topic_id | post_status | post_time | post_text
.

Comunque è la performance cade a parte quando ci sono un milione di messaggi e l'utente stesso ha decine di migliaia di messaggi. MySQL non può più ordinare la tabella in memoria o ci sono troppe righe per la scansione. Può richiedere fino a 3 secondi nell'uso realworld che è inaccettabile IMHO perché sta spunendo la CPU durante quel tempo e rallentando tutti gli altri.

Posso fare qualsiasi combinazione di indice, naturalmente, ma MySQL sembra per lo più per usare una combinazione di

poster_id + post_time 
.

Quindi seleziona solo i post 50k dell'utente fuori dal milione e poi inizia a raggruppamento di Topic_ID e ordinamento. Stranamente aggiungendo argomento_ID nell'indice Mix non sembra aiutare le prestazioni, anche se potrebbe essere l'ordine dei campi indice?

Ho provato a scrivere un join equivalente invece quindi posso usare più di un indice ma ho incontrato problemi con il fatto che ogni lato deve essere filtrato da post_status e poster.

Stavo pensando che sarebbe stato più veloce, almeno per le prime pagine, se MySQL potesse essere effettuato per prima ordinare i dati tramite il suo indice da Post_Time e quindi iniziare a scegliere il distinto topic_id per l'utente in discendente ordine. Immagino che richiederebbe una sottoquery e non è sicuro che una sottoquery dei risultati 50k sarebbe migliore, ha ancora bisogno di una tabella temporanea.

Naturalmente una soluzione fondamentale sarebbe di aumentare il design principale in modo che ci sia un'altra tabella che memorizza solo il Max Post_Time per ogni utente in ogni argomento, ma questo è troppo grande di un cambiamento a meno che non sia possibile trovare altre soluzione.

Grazie per qualsiasi suggerimento!


.

Aggiunta di un esempio di realworld e spiega:

log lento

# Query_time: 2.751334  Lock_time: 0.000056 Rows_sent: 40  Rows_examined: 48286
SELECT   p.*, MAX(post_time) as post_time FROM forum_posts AS p   WHERE p.poster_id = '2' AND p.post_status = '0' GROUP BY p.topic_id  ORDER BY post_time DESC LIMIT 7000, 40;
.

Spiega

select_type     table   type    possible_keys   key     key_len     ref     rows    Extra
SIMPLE          p   ref poster_time poster_time 4   const   27072   Using where; Using temporary; Using filesort
.

È stato utile?

Soluzione

In primo luogo, correggi la tua query per fornire risultati determinati:

SELECT p.topic_id, 
       MAX(post_time) as post_time 
FROM forum_posts AS p   
WHERE p.poster_id = '1' AND p.post_status = '0' 
GROUP BY p.topic_id  
ORDER BY post_time DESC 
  LIMIT 50 ;
.

Quindi provalo dopo aver aggiunto un indice su (post_status, poster_id, topic_id, post_time).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top