2008-09-21 6 views
8

Tengo una tabla a la que hacen referencia las claves foráneas en muchas otras tablas. En mi programa, si quiero eliminar una de estas filas, primero necesito buscar dependencias y presentarlas al usuario: "Este objeto depende de x de la tabla y, z de la tabla q, etc.". También espero que el número de tablas que tienen claves externas a esta tabla crezca considerablemente con el tiempo.¿Está consultando la base de datos de información de MySQL una buena manera de encontrar tablas relacionadas?

¿Es la base de datos de information_schema una buena forma de hacer una búsqueda de todas las dependencias? Traté de consultarlo para recuperar una lista de todas las tablas que tienen claves externas a mi tabla, luego iterar sobre el resultado y seleccionar todas las entradas de cada tabla donde el valor de la clave externa coincide con el valor que el usuario está tratando de eliminar. La consulta que tengo es la siguiente:

SELECT * FROM `KEY_COLUMN_USAGE` kcu 
LEFT JOIN TABLE_CONSTRAINTS tc 
ON tc.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME 
WHERE tc.CONSTRAINT_TYPE='FOREIGN KEY' 
AND (kcu.REFERENCED_TABLE_SCHEMA='db') 
AND (kcu.REFERENCED_TABLE_NAME = 'testtable') 

que funciona perfectamente para la determinación de las tablas que tengo que buscar, sin embargo, es muy lento. La consulta tarda de 1 a 2 segundos en el mejor de los casos para ejecutarse en mi máquina de desarrollo, lo que reducirá mucho cuando la ejecute en mi servidor de producción, pero seguirá siendo bastante lenta.

Necesito saber si es una mala idea usar information_schema de esta manera. Si no, cómo puedo extraer un mejor rendimiento de la consulta. ¿La consulta que estoy usando es sólida o hay una mejor manera de hacerlo? Si es así, ¿cuál es la mejor manera de abordar este problema desde una perspectiva de mantenimiento?

Respuesta

4

Dvorak tiene razón, INFORMATION_SCHEMA está destinado a eso.

En cuanto a los problemas de rendimiento, hay varias maneras en que puede mejorar el rendimiento

  • manera fácil, pero no mejora mucho vendrán de ella: almacenar la información en una variable estática. Al menos la consulta solo se realizará una vez por página

  • Usar el almacenamiento en caché persistente: el caché de PHP alternativo puede ayudarlo (consulte http://fr3.php.net/manual/en/book.apc.php). La información que obtendrá del esquema de información es un buen candidato para almacenar en un caché persistente.

  • utilizar una biblioteca de ORM, como doctrina (http://www.doctrine-project.org/) Una mirada a la lib archivo/Doctrina/Importar/Mysql.php mostrará que hace exactamente lo que necesita, y mucho más.

+0

De acuerdo con [un artículo] (http://www.mysqlperformanceblog.com/2011/12/23/solving-information_schema-slowness /) por Peter Zaitsev, recomienda este comando: 'set global innodb_stats_on_metadata = 0'. – Mei

3

Creo que este es exactamente el tipo de cosas para las que está destinado INFORMATION_SCHEMA.

2

Usando INFORMATION_SCHEMA de esto es OK en sistemas estáticos o administrativas, pero no se recomienda para una función de aplicación transaccional como INFORMATION_SCHEMA es, probablemente, implementado como puntos de vista sobre la parte superior del diccionario de datos del sistema nativo.

Esta sería una forma bastante ineficiente de hacer una operación 'D' genérica para una biblioteca CRUD. Además, en muchos sistemas (viene a la mente Oracle), el diccionario de datos del sistema se implementa realmente como vistas en una estructura de datos de nivel inferior. Esto significa que el diccionario de datos del sistema nativo tampoco puede ser adecuado para esto. El diccionario de datos del sistema también puede cambiar de una versión a otra.

Debe haber relativamente pocos casos en los que una "eliminación" directa de un registro y todos sus hijos sea el camino correcto a seguir. Hacer esto como una función genérica puede obtener poco beneficio práctico.Además, si las claves externas no están presentes en la base de datos, los niños huérfanos yacerán allí porque este enfoque depende de que los FK estén presentes para saber qué niños eliminar.

1

Se ralentiza el funcionamiento de mis aplicaciones, pero necesito los datos de restricción de clave externa para que todo se enganche correctamente.

Las demoras son enormes al consultar el esquema de información, y crean una página que solía cargar al instante, cargan en 3-4 segundos.

Bueno, al menos las restricciones de clave externa están disponibles en MySQL 5, lo que hace que el desarrollo de aplicaciones sea más robusto, pero obviamente a un costo.

personas se han quejado de este problema desde el año 2006 en base a mis búsquedas de Google, y el problema sigue siendo - no deben ser una solución fácil; - (

3

que estaba buscando en esto, así que quiero. use KEY_COLUMN_USAGE para algunos CRUD. Y noté que no hay claves o índices disponibles en estas tablas. Esa podría ser la razón del bajo rendimiento.

1

En caso de que esto se encuentre en google, también vale la pena mencionarlo que el information_schema ocasionalmente difiere de lo devuelto por show create table.

T aquí hay un buen ejemplo de esto en este DBA Stack Exchange thread. Después de ejecutar este comando:

create table rolando (num int not null, primary key (num) using hash); 

comprobar los resultados:

mysql> show create table rolando\G 
    (...) 
    PRIMARY KEY (`num`) USING HASH 

mysql> show indexes from rolando; 
(...) | Index_type | (...) 
(...) | BTREE  | (...) 
Cuestiones relacionadas