Práctica de ajuste de MySQL
记一次实习MySQL调优
Requisito comercial: visualización de publicaciones populares
- Cuente la cantidad de comentarios y vistas de la publicación dentro de un cierto período de tiempo y ordene en orden descendente según la cantidad de comentarios, vistas y tiempo de creación de la publicación.
Tres tablas: app_invitation
tabla de publicaciones, app_invitation_comment
tabla de comentarios de publicaciones, app_invitation_look
tabla de registros de exploración de publicaciones
Pasos de ajuste
Fondo de sintonización: la parte desarrollada por el ex empleado tenía una pequeña cantidad de datos durante la prueba y no se encontró ningún problema de velocidad de respuesta demasiado lenta. La cantidad de datos aumentó y la velocidad de respuesta fue demasiado lenta, por lo que debe ser optimizado
-
Primero verifique si el código necesita ser optimizado:
- No es necesario procesar todos los datos consultados, pero si procesar la parte que se desea visualizar
-
Escribir sentencias SQL
La declaración sql original está escrita de forma redundante, y tanto la unión de la tabla como la subconsulta deben obtener el mismo punto de información.
<select id="moreHotList" resultType="AppInvitation" > SELECT count(b.id) count,a.look, (SELECT IFNULL(sum(look),0) from app_invitation_look where create_time BETWEEN #{start} and #{end} and invitation_id = a.id) look2, a.id, a.type,a.tile_category tileCategory, a.tile_specification tileSpecification,a.description, a.uid, a.phone, a.city, a.hot, a.top, a.longitude, a.latitude, a.enterprise,a.machine_trial machineTrial, a.state, a.dev, a.create_time createTime, a.update_time updateTime FROM app_invitation a LEFT JOIN app_invitation_comment b ON a.id = b.invitation_id LEFT JOIN app_invitation_look c on a.id = c.invitation_id where a.dev = 1 AND a.state = 1 AND a.machine_trial = 1 GROUP BY a.id <if test="last != null "> and a.update_time <= #{last} </if> ORDER BY count desc,look2 desc,a.create_time desc </select>
-
Mirando
explain
el plan de ejecución, el tipo de las dos tablas esall
- Respectivamente app_invitation_comment post tabla de comentarios, app_invitation_look post tabla de registro de navegación
建立invitation_id的索引
- Resultado: el tipo de subconsulta y parte de la tabla de unión es
ref
- Respectivamente app_invitation_comment post tabla de comentarios, app_invitation_look post tabla de registro de navegación
-
Columna adicional para consulta de tabla de publicaciones
using temporary、using filesort
-
innodb_buffer_pool_size
Usando temporal, a través de la búsqueda en línea, se encuentra que la tabla temporal puede configurarse porque la configuración es demasiado pequeña. A través de mostrar variables como "% innodb_buffer_pool_size%", se encuentra que la configuración existente es 128M, y se modifica a 256M -
El uso de la clasificación de archivos se ordena en la memoria. El campo de clasificación es el campo que se calcula mediante el uso de la tabla conjunta/subconsulta, por lo que no es fácil crear un índice:
(Nota: el siguiente tiempo de ejecución se debe a que el autor está ejecutando en una base de datos con una pequeña cantidad de datos y es solo para visualización)
-
Al
set profiling = 1;
ejecutar la instrucción sql,show profiles
puede ver el tiempo de ejecución específico -
Puede pasar mostrar perfil para la consulta query_id, query_id, que corresponde al valor específico de la columna Query_ID,
Es decir,
show profile for query 2;
puede ver el tiempo específico dedicado a cada paso -
Se encuentra que la ordenación toma más tiempo. El campo de ordenación es un campo obtenido usando una subconsulta, por lo que no es fácil construir un índice; usando ordenación de archivos ordena en la memoria, y hay dos métodos de ordenación, que determinan la configuración de parámetros de el método de clasificación El valor predeterminado es 1 MB, que es una
sort_buffer_size
clasificación de una sola vía, elija aumentar el valor del parámetro -
El tiempo de creación de uno de los campos de clasificación se correlaciona positivamente con la identificación de incremento automático, así que cambie create_time a id
-
Combinado con las necesidades comerciales, la base de datos contendrá publicaciones eliminadas lógicamente, es decir, no es necesario recuperar todas las publicaciones. Originalmente, la declaración where se usaba para filtrar las tablas después de unirse, pero el autor cambió para filtrar las publicaciones antes de unirse.
-
-
-
Versión definitiva:
<select id="moreHotList" resultType="AppInvitation" >
SELECT count(b.id) comment,a.look,
(SELECT IFNULL(sum(look),0) from app_invitation_look where create_time BETWEEN #{start} and #{end} and invitation_id = a.id) look2,
a.id, a.type,a.tile_category tileCategory, a.tile_specification tileSpecification,
a.description, a.uid, a.phone, a.city, a.hot, a.top, a.longitude, a.latitude, a.enterprise,
a.machine_trial machineTrial, a.state, a.dev, a.create_time createTime, a.update_time updateTime
FROM (SELECT * FROM app_invitation where dev = 1 AND state = 1 AND machine_trial = 1
<if test="last != null ">
and update_time <= #{last}
</if>
) a
LEFT JOIN app_invitation_comment b
on a.id = b.invitation_id and b.create_time BETWEEN #{start} and #{end} and b.hidden = 2 and b.machine_trial = 1 and b.dev = 2
GROUP BY a.id
ORDER BY comment desc,look2 desc,a.id desc
</select>
and b.dev = 2
GROUP BY a.id
ORDER BY comment desc,look2 desc,a.id desc
</select>