Pregunta

Estoy tratando de encontrar una manera directa de mejorar el rendimiento de los foros muy activos donde hay una gran cantidad de publicaciones y MySQL ya no puede hacer clases de tabla en la memoria y no parece aprovechar al máximo los índices. < / p>

Esta sencilla consulta encuentra la publicación más reciente en cada tema para que un usuario determine si tiene alguna respuesta desde entonces (al comparar más tarde el Topic_Time)

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

la mesa plana simple, se ve algo como

post_id | poster_id | topic_id | post_status | post_time | post_text

Sin embargo, su desempeño se desmorona cuando hay un millón de puestos y el usuario tienen decenas de miles de publicaciones. MySQL ya no puede ordenar la tabla en la memoria o hay demasiadas filas para escanear. Puede tomar hasta 3 segundos en el uso del mundo real, lo cual es inaceptable, ya que está grabando la CPU durante ese tiempo y desacelerando a todos los demás.

Puedo hacer cualquier combinación de índice, por supuesto, pero MySQL parece que en su mayoría le gusta usar un combo de

poster_id + post_time 

Por lo tanto, simplemente selecciona las publicaciones de 50K de un usuario de los millones y luego comienza a agrupar por Topic_ID y clasificación. Extrañamente agregar topic_id a la mezcla de índice no parece ayudar al rendimiento, ¡aunque puede ser el orden de los campos de índice?

He intentado escribir una unión equivalente en su lugar, para que pueda usar más de un índice, pero me encuentro con problemas con el hecho de que cada lado tiene que ser filtrado por Post_Status y Poster.

Estaba pensando que sería más rápido, al menos para las primeras páginas, si se pudiera hacer MySQL para ordenar primero los datos a través de su índice por correo postal y luego comenzar a seleccionar el topic_id distinto para el usuario en descender pedido. Supongo que eso requeriría una subconsulta y no estaría seguro de que una subconsía de resultados de 50k sería mejor, aún necesita una tabla temporal.

Por supuesto, una solución fundamental sería aumentar el diseño central para que haya otra tabla, que solo almacena el Max Post_Time para cada usuario en cada tema, pero esto es demasiado grande de un cambio a menos que no se pueda encontrar ninguna otra solución.

¡Gracias por alguna sugerencia!


agregando ejemplo realworld y explique:

log

# 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;

explique

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

¿Fue útil?

Solución

Primero, arregle su consulta para proporcionar resultados determinados:

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 ;

Luego inténtelo después de agregar un índice en (post_status, poster_id, topic_id, post_time).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top