Mi aplicación depende de ejecutar "mostrar columnas" para ciertas tablas. Tarda unos 60 ms en ejecutarse, mientras que todas nuestras otras consultas toman menos de un ms. Consultar information_schema
directamente es aún más lento.
La base de datos contiene aproximadamente 250 bases de datos, con 100 a 200 tablas por base de datos (aproximadamente 20k tablas en total).
- ¿Cómo puedo averiguar por qué estas operaciones son tan lentas?
- ¿Quizás haya alguna configuración que pueda cambiar para que se ejecute más rápido o para almacenarla en caché en el lado de SQL?
(La aplicación realiza alrededor de 14 consultas de este tipo por carga de página; soy consciente de que este código heredado debe limpiarse, pero busco posibles opciones mientras trabajo en la solución a largo plazo).
Respuestas:
MySQL recalcula las estadísticas de la tabla para ciertas operaciones que acceden a las
INFORMATION_SCHEMA
tablas (SHOW COLUMNS
es solo un alias conveniente para realizar consultasINFORMATION_SCHEMA.COLUMNS
). Establezca innodb_stats_on_metadata en falso, lo que evitará que este recálculo ocurra cuando solicite metadatos de la tabla.y agregue lo siguiente a
my.cnf
fuente
[mysqld]
allí. Puede ser obvio para muchos que esta configuración iría bajo mysqld, pero puede no ser obvio para aquellos que harían esta pregunta. Por cierto, esto aceleróSELECT COUNT(*)
en una de misinformation_schema
mesas a 6 segundos desde más de un minuto. Todavía lento, pero una gran mejora.Le sugiero que cree una base de datos que tenga las
INFORMATION_SCHEMA
tablas (o solo aquellas que necesita) como réplicas. Indícelos adecuadamente y obtendrá un aumento de rendimiento.Sin
INFORMATION_SCHEMA
embargo, el problema de la sincronización entre esta base de datos es complicado.Podría tener un procedimiento que sincronice estas tablas cada hora o cada 5 minutos (¿con qué frecuencia se cambia la estructura de las tablas?).
Otra idea sería utilizar MySQL Proxy para capturar cualquier
ALTER TABLE
declaraciones (yCREATE
, yDROP
, yCREATE INDEX
, y cualquier otras declaraciones modificar la información que necesita) y luego sincronizar el esquema de información replicada después de estas declaraciones tienen éxito.Si solo necesita los nombres de columna y ninguna otra información, como el tipo de datos, la longitud o los índices disponibles, tal vez podría reemplazar el uso de
SHOW COLUMNS
consultas (rápidas) que devuelven solo 1 fila, conLIMIT 1
o ninguna, conLIMIT 0
o:A pesar de los consejos generales contra el uso de
SELECT *
, este puede ser un caso legítimo donde nada más es útil. (¡todo lo demás*
, pero puede provocar un error!)fuente
En este caso particular, creo que
INFORMATION_SCHEMA
es un arenque rojo. Según mis propias pruebas deSHOW COLUMNS
rendimiento, lainnodb_stats_on_metadata
variable no parece hacer ninguna diferencia en las tablas MyISAM o InnoDB.Sin embargo, del manual de MySQL 5.0 ...
Esto parece haberse eliminado del manual a partir de MySQL 5.5, pero aún parece aplicarse en esa versión ...
La información de campo devuelta con un conjunto de resultados de la consulta contiene la misma información que la devuelta
SHOW COLUMNS
, por lo que seSELECT * FROM my_table LIMIT 0
debe lograr lo mismo sin crear una tabla temporal en disco por consulta.Un ejemplo rápido para tomar los nombres de campo en PHP ...
Recuperar información de campo de esta manera es un poco más incómodo de decodificar. Tendrá que consultar la descripción de la
MYSQL_FIELD
estructura subyacente para extraer los tipos de datos y las marcas, pero se ejecuta aproximadamente 7 veces más rápido en mi sistema.fuente
Me gusta la primera sugerencia en la respuesta de @ yerpcube (+1), pero me gustaría proponer algo
--no-data
--routines
--triggers
--all-databases
o--databases
seguido de una lista de bases de datos que deseaPor lo tanto, mysqldump debería tener el siguiente aspecto:
Eso es. En el futuro, todo lo que necesita hacer es conectarse a esta instancia de base de datos del puerto 3307 y ejecutar cualquier consulta relacionada con el esquema al contenido de su corazón. Si conoce alguna tabla en la base de datos de producción que cambie, solo mysqldump el esquema de producción y vuelva a cargarlo en la instancia del puerto 3307.
ADVERTENCIA: Si instala una instancia de mysql en la misma máquina que producción, asegúrese absolutamente de conectarse a esa instancia usando
Si ejecutas
Manguera de producción. Así que ten cuidado !!!!
Una alternativa sería usar un servidor de base de datos separado.
fuente