MySQL GroupWise Problemas máximos de rendimiento en un millón de tablas de fila
-
13-12-2019 - |
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
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)
.