sql >> Base de Datos >  >> RDS >> Mysql

Consultando el ESQUEMA DE INFORMACIÓN de MySQL:¿Por qué? ¿Cómo?

Las bases de datos deben funcionar de manera óptima, pero esa no es una tarea tan fácil. La base de datos INFORMATION SCHEMA puede ser su arma secreta en la guerra de la optimización de bases de datos.

Estamos acostumbrados a crear bases de datos utilizando una interfaz gráfica o una serie de comandos SQL. Eso está completamente bien, pero también es bueno comprender un poco lo que sucede en segundo plano. Esto es importante para la creación, el mantenimiento y la optimización de una base de datos, y también es una buena manera de realizar un seguimiento de los cambios que ocurren "detrás de escena".

En este artículo, veremos un puñado de consultas SQL que pueden ayudarlo a observar el funcionamiento de una base de datos MySQL.

La base de datos INFORMACION_ESQUEMA

Ya discutimos el INFORMATION_SCHEMA base de datos en este artículo. Si aún no lo ha leído, definitivamente le sugiero que lo haga antes de continuar.

Si necesita un repaso en el INFORMATION_SCHEMA base de datos, o si decide no leer el primer artículo, aquí hay algunos datos básicos que necesita saber:

  • El INFORMATION_SCHEMA La base de datos es parte del estándar ANSI. Trabajaremos con MySQL, pero otros RDBMS tienen sus variantes. Puede encontrar versiones para H2 Database, HSQLDB, MariaDB, Microsoft SQL Server y PostgreSQL.
  • Esta es la base de datos que realiza un seguimiento de todas las demás bases de datos en el servidor; encontraremos descripciones de todos los objetos aquí.
  • Como cualquier otra base de datos, el INFORMATION_SCHEMA La base de datos contiene varias tablas relacionadas e información sobre diferentes objetos.
  • Puede consultar esta base de datos usando SQL y usar los resultados para:
    • Supervisar el estado y el rendimiento de la base de datos, y
    • Genera código automáticamente en función de los resultados de la consulta.

Ahora pasemos a consultar la base de datos INFORMACION_ESQUEMA. Empezaremos mirando el modelo de datos que vamos a utilizar.

El modelo de datos

El modelo que usaremos en este artículo se muestra a continuación.




Este es un modelo simplificado que nos permite almacenar información sobre clases, instructores, estudiantes y otros detalles relacionados. Repasemos brevemente las tablas.

Guardaremos la lista de instructores en el lecturer mesa. Para cada profesor, registraremos un first_name y un last_name .

La class tabla enumera todas las clases que tenemos en nuestra escuela. Para cada registro en esta tabla, almacenaremos el class_name , el ID del profesor, una start_date planificada y end_date y cualquier class_details adicional . En aras de la simplicidad, supondré que solo tenemos un profesor por clase.

Las clases generalmente se organizan como una serie de conferencias. Generalmente requieren uno o más exámenes. Almacenaremos listas de clases y exámenes relacionados en la class y exam mesas. Ambos tendrán el ID de la clase relacionada y el start_time esperado y end_time .

Ahora necesitamos estudiantes para nuestras clases. Una lista de todos los estudiantes se almacena en el student mesa. Una vez más, almacenaremos solo el first_name y el last_name de cada alumno.

Lo último que debemos hacer es realizar un seguimiento de las actividades de los estudiantes. Guardaremos una lista de cada clase en la que se registró un estudiante, el registro de asistencia del estudiante y los resultados de sus exámenes. Cada una de las tres tablas restantes:on_class , on_lecture y on_exam – Tendrá una referencia al alumno y una referencia a la tabla correspondiente. Solo el on_exam la tabla tendrá un valor adicional:grado.

Sí, este modelo es muy sencillo. Podríamos añadir muchos otros detalles sobre estudiantes, profesores y clases. Podríamos almacenar valores históricos cuando los registros se actualizan o eliminan. Aún así, este modelo será suficiente para los propósitos de este artículo.

Crear una base de datos

Estamos listos para crear una base de datos en nuestro servidor local y examinar lo que sucede dentro de ella. Exportaremos el modelo (en Vertabelo) usando el “Generate SQL script " botón.

Luego crearemos una base de datos en la instancia del servidor MySQL. Llamé a mi base de datos “classes_and_students ”.

Lo siguiente que debemos hacer es ejecutar un script SQL generado previamente.

Ahora tenemos la base de datos con todos sus objetos (tablas, claves primarias y externas, claves alternativas).

Tamaño de la base de datos

Después de que se ejecuta el script, los datos sobre las "classes and students ” la base de datos se almacena en el INFORMATION_SCHEMA base de datos. Estos datos están en muchas tablas diferentes. No los enumeraré a todos nuevamente aquí; lo hicimos en el artículo anterior.

Veamos cómo podemos usar SQL estándar en esta base de datos. Comenzaré con una consulta muy importante:

SET @table_schema = "classes_and_students";

SELECT 

    ROUND(SUM( INFORMATION_SCHEMA.TABLES.DATA_LENGTH + INFORMATION_SCHEMA.TABLES.INDEX_LENGTH ) / 1024 / 1024, 2) AS "DB Size (in MB)",
    ROUND(SUM( INFORMATION_SCHEMA.TABLES.DATA_FREE )/ 1024 / 1024, 2) AS "Free Space (in MB)"
    
FROM INFORMATION_SCHEMA.TABLES
WHERE INFORMATION_SCHEMA.TABLES.TABLE_SCHEMA = @table_schema;

Solo estamos consultando INFORMATION_SCHEMA.TABLES mesa aquí. Esta tabla debería darnos detalles más que suficientes sobre todas las tablas en el servidor. Tenga en cuenta que he filtrado solo las tablas de "classes_and_students " base de datos usando el SET variable en la primera línea y luego usando este valor en la consulta. La mayoría de las tablas contienen las columnas TABLE_NAME y TABLE_SCHEMA , que denotan la tabla y el esquema/base de datos al que pertenecen estos datos.

Esta consulta devolverá el tamaño actual de nuestra base de datos y el espacio libre reservado para nuestra base de datos. Aquí está el resultado real:

Como era de esperar, el tamaño de nuestra base de datos vacía es inferior a 1 MB y el espacio libre reservado es mucho mayor.

Tamaños y propiedades de las tablas

La próxima cosa interesante a hacer sería mirar los tamaños de las tablas en nuestra base de datos. Para ello, utilizaremos la siguiente consulta:

SET @table_schema = "classes_and_students";

SELECT 

	INFORMATION_SCHEMA.TABLES.TABLE_NAME,
    ROUND(SUM( INFORMATION_SCHEMA.TABLES.DATA_LENGTH + INFORMATION_SCHEMA.TABLES.INDEX_LENGTH ) / 1024 / 1024, 2) "Table Size (in MB)",
	ROUND(SUM( INFORMATION_SCHEMA.TABLES.DATA_FREE )/ 1024 / 1024, 2) AS "Free Space (in MB)",
	MAX( INFORMATION_SCHEMA.TABLES.TABLE_ROWS) AS table_rows_number,
	MAX( INFORMATION_SCHEMA.TABLES.AUTO_INCREMENT) AS auto_increment_value

FROM INFORMATION_SCHEMA.TABLES
WHERE INFORMATION_SCHEMA.TABLES.TABLE_SCHEMA = @table_schema
GROUP BY INFORMATION_SCHEMA.TABLES.TABLE_NAME
ORDER BY 2 DESC;

La consulta es casi idéntica a la anterior, con una excepción:el resultado se agrupa en el nivel de la tabla.

Aquí hay una imagen del resultado devuelto por esta consulta:

Primero, podemos notar que las ocho mesas tienen un “Tamaño de mesa” mínimo reservado para la definición de tablas, que incluye las columnas, la clave principal y el índice. El “Espacio Libre” se distribuye por igual entre todas las tablas.

También podemos ver el número de filas actualmente en cada tabla y el valor actual del auto_increment propiedad de cada tabla. Dado que todas las tablas están completamente vacías, no tenemos datos y auto_increment se establece en 1 (un valor que se asignará a la siguiente fila insertada).

Claves primarias

Cada tabla debe tener un valor de clave principal definido, por lo que es aconsejable verificar si esto es cierto para nuestra base de datos. Una forma de hacerlo es unir una lista de todas las tablas con una lista de restricciones. Esto debería darnos la información que necesitamos.

SET @table_schema = "classes_and_students";

SELECT 

	tab.TABLE_NAME,
    COUNT(*) AS PRI_number

FROM INFORMATION_SCHEMA.TABLES tab
LEFT JOIN (
    SELECT

        INFORMATION_SCHEMA.COLUMNS.TABLE_SCHEMA,
        INFORMATION_SCHEMA.COLUMNS.TABLE_NAME

    FROM INFORMATION_SCHEMA.COLUMNS
    WHERE INFORMATION_SCHEMA.COLUMNS.TABLE_SCHEMA  = @table_schema
    AND INFORMATION_SCHEMA.COLUMNS.COLUMN_KEY = 'PRI'
) col 
	ON tab.TABLE_SCHEMA = col.TABLE_SCHEMA
    AND tab.TABLE_NAME = col.TABLE_NAME
WHERE tab.TABLE_SCHEMA = @table_schema
GROUP BY 
	tab.TABLE_NAME;

También hemos utilizado INFORMATION_SCHEMA.COLUMNS tabla en esta consulta. Mientras que la primera parte de la consulta simplemente devolverá todas las tablas en la base de datos, la segunda parte (después de LEFT JOIN ) contará el número de PRI en estas tablas. Usamos LEFT JOIN porque queremos ver si una tabla tiene 0 PRI en las COLUMNS mesa.

Como era de esperar, cada tabla en nuestra base de datos contiene exactamente una columna de clave principal (PRI).

¿"Islas"?

Las “islas” son mesas que están completamente separadas del resto del modelo. Suceden cuando una tabla no contiene claves foráneas y no se hace referencia a ninguna otra tabla. Esto realmente no debería ocurrir a menos que haya una muy buena razón, p. cuando las tablas contienen parámetros o almacenan resultados o informes dentro del modelo.

SET @table_schema = "classes_and_students";

SELECT 

	tab.TABLE_NAME,
    (CASE WHEN f1.number_referenced IS NULL THEN 0 ELSE f1.number_referenced END) AS number_referenced,
    (CASE WHEN f2.number_referencing IS NULL THEN 0 ELSE f2.number_referencing END) AS number_referencing

FROM INFORMATION_SCHEMA.TABLES tab
LEFT JOIN 

-- # table was used as a reference
(
    SELECT 
        INFORMATION_SCHEMA.KEY_COLUMN_USAGE.REFERENCED_TABLE_SCHEMA,
        INFORMATION_SCHEMA.KEY_COLUMN_USAGE.REFERENCED_TABLE_NAME,
        COUNT(*) AS number_referenced
    FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE 
    WHERE INFORMATION_SCHEMA.KEY_COLUMN_USAGE.REFERENCED_TABLE_SCHEMA = @table_schema
    GROUP BY
        INFORMATION_SCHEMA.KEY_COLUMN_USAGE.REFERENCED_TABLE_SCHEMA,
        INFORMATION_SCHEMA.KEY_COLUMN_USAGE.REFERENCED_TABLE_NAME
) f1 
	ON tab.TABLE_SCHEMA = f1.REFERENCED_TABLE_SCHEMA
    AND tab.TABLE_NAME = f1.REFERENCED_TABLE_NAME

LEFT JOIN

-- # of references in the table
(
    SELECT 
        INFORMATION_SCHEMA.KEY_COLUMN_USAGE.TABLE_SCHEMA,
        INFORMATION_SCHEMA.KEY_COLUMN_USAGE.TABLE_NAME,
        COUNT(*) AS number_referencing
    FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE 
    WHERE INFORMATION_SCHEMA.KEY_COLUMN_USAGE.REFERENCED_TABLE_SCHEMA = @table_schema
    AND INFORMATION_SCHEMA.KEY_COLUMN_USAGE.REFERENCED_TABLE_NAME IS NOT NULL
    GROUP BY
        INFORMATION_SCHEMA.KEY_COLUMN_USAGE.TABLE_SCHEMA,
        INFORMATION_SCHEMA.KEY_COLUMN_USAGE.TABLE_NAME
) f2 
	ON tab.TABLE_SCHEMA = f2.TABLE_SCHEMA
    AND tab.TABLE_NAME = f2.TABLE_NAME    
    
WHERE tab.TABLE_SCHEMA = @table_schema;

¿Cuál es la idea detrás de esta consulta? Bueno, estamos usando el INFORMATION_SCHEMA.KEY_COLUMN_USAGE table para comprobar si alguna columna de la tabla es una referencia a otra tabla o si alguna columna se utiliza como referencia en otra tabla. La primera parte de la consulta selecciona todas las tablas. Después del primer LEFT JOIN, contamos el número de veces que se usó cualquier columna de esta tabla como referencia. Después del segundo LEFT JOIN, contamos el número de veces que cualquier columna de esta tabla hace referencia a cualquier otra tabla.

El resultado devuelto es:

En la fila de la class tabla, los números 3 y 1 indican que esta tabla fue referenciada tres veces (en la lecture , exam y on_class tablas) y que contiene un atributo que hace referencia a otra tabla (lecturer_id ). Las otras tablas siguen un patrón similar, aunque los números reales, por supuesto, serán diferentes. La regla aquí es que ninguna fila debe tener un 0 en ambas columnas.

Agregar filas

Hasta ahora, todo ha ido como se esperaba. Hemos importado con éxito nuestro modelo de datos de Vertabelo al servidor MySQL local. Todas las tablas contienen claves, tal como queremos, y todas las tablas están relacionadas entre sí:no hay "islas" en nuestro modelo.

Ahora, insertaremos algunas filas en nuestras tablas y usaremos las consultas demostradas anteriormente para rastrear los cambios en nuestra base de datos.

Después de agregar 1000 filas en la tabla del profesor, volveremos a ejecutar la consulta desde "Table Sizes and Properties " sección. Devolverá el siguiente resultado:

Podemos notar fácilmente que la cantidad de filas y los valores de incremento automático han cambiado como se esperaba, pero no hubo cambios significativos en el tamaño de la tabla.

Este fue solo un ejemplo de prueba; en situaciones de la vida real, notaríamos cambios significativos. El número de filas cambiará drásticamente en tablas rellenadas por usuarios o procesos automatizados (es decir, tablas que no son diccionarios). Verificar el tamaño y los valores en tales tablas es una muy buena manera de encontrar y corregir rápidamente comportamientos no deseados.

¿Te importa compartir?

Trabajar con bases de datos es una búsqueda constante para lograr un rendimiento óptimo. Para tener más éxito en esa búsqueda, debe utilizar cualquier herramienta disponible. Hoy hemos visto algunas consultas que son útiles en nuestra lucha por un mejor rendimiento. ¿Has encontrado algo más útil? ¿Has jugado con el INFORMATION_SCHEMA base de datos antes? Comparte tu experiencia en los comentarios a continuación.