¿Foreign Key mejora el rendimiento de las consultas?

149

Supongamos que tengo 2 tablas, Productos y Categorías de productos. Ambas tablas tienen relación en CategoryId. Y esta es la consulta.

SELECT p.ProductId, p.Name, c.CategoryId, c.Name AS Category
FROM Products p
INNER JOIN ProductCategories c ON p.CategoryId = c.CategoryId
WHERE c.CategoryId = 1;

Cuando creo un plan de ejecución, la tabla ProductCategories realiza la búsqueda de índice de clúster, que es lo que se espera. Pero para Table Products, realiza un escaneo de índice de clúster, lo que me hace dudar. ¿Por qué FK no ayuda a mejorar el rendimiento de las consultas?

Entonces tengo que crear un índice en Products.CategoryId. Cuando creo nuevamente el plan de ejecución, ambas tablas realizan la búsqueda de índice. Y el costo estimado del subárbol se reduce mucho.

Mis preguntas son:

  1. Además de FK ayuda en la restricción de la relación, ¿tiene alguna otra utilidad? ¿Mejora el rendimiento de la consulta?

  2. ¿Debo crear un índice en todas las columnas FK (me gusta Products.CategoryId) en todas las tablas?

Chaowlert Chaisrichalermpol
fuente

Respuestas:

186

Las claves externas son una herramienta de integridad referencial, no una herramienta de rendimiento. Al menos en SQL Server, la creación de un FK no crea un índice asociado, y debe crear índices en todos los campos FK para mejorar los tiempos de búsqueda.

cmsjr
fuente
40
Los buenos modelos (generalmente) funcionan mejor.
Kenny Evitt
10
"Las claves externas son una herramienta de integridad relacional". Utilice la palabra 'relacional' con cuidado. Las claves externas son un concepto de base de datos, una abreviatura de una restricción de integridad referencial. No son parte del modelo relacional. Supongo que cometiste un error tipográfico.
cuando el
77
@Kenny A menudo sí, pero a veces un modelo mejor cuesta más. Caso en cuestión: las claves foráneas causan más procesamiento, no menos.
Hans
8
claves externas hacen mejorar el rendimiento, al menos en MySQL. Además, tiene razón, la creación de un FK no crea un índice; la creación de un FK requiere un índice
Félix Gagnon-Grenier
15
Esta respuesta es bastante inútil porque no responde la pregunta. Es bueno saber que las claves externas no tienen la intención de tener un efecto (positivo) en el rendimiento, pero la pregunta era sobre la realidad, no sobre las intenciones.
John
58

Foreign Keys puede mejorar (y dañar) el rendimiento

  1. Como se indica aquí: las claves externas aumentan el rendimiento

  2. Siempre debe crear índices en columnas FK para reducir las búsquedas. SQL Server no hace esto automáticamente.

Editar

Como el enlace ahora parece estar muerto (felicitaciones a Chris por darse cuenta) , a continuación se muestra la esencia de por qué las claves externas pueden mejorar (y dañar) el rendimiento.

La clave externa puede mejorar el rendimiento

La restricción de clave externa mejora el rendimiento en el momento de leer los datos, pero al mismo tiempo reduce el rendimiento en el momento de insertar / modificar / eliminar datos.

En caso de leer la consulta, el optimizador puede usar restricciones de clave externa para crear planes de consulta más eficientes, ya que las restricciones de clave externa son reglas previamente declaradas. Esto generalmente implica omitir alguna parte del plan de consulta porque, por ejemplo, el optimizador puede ver que debido a una restricción de clave externa, no es necesario ejecutar esa parte particular del plan.

Lieven Keersmaekers
fuente
3
Aquí hay un enlace que detalla las formas en que pueden degradar el rendimiento devx.com/getHelpOn/10MinuteSolution/16595/0/page/2
cmsjr
3
Eso tiene sentido, pero solo se encontrará con esto con una declaración de eliminación masiva. Quizás la conclusión debería ser que en entornos OLAP, los FK no indexados mejorarían el rendimiento, mientras que en entornos OLTP, degradarían el rendimiento.
Lieven Keersmaekers
1
El enlace en esta respuesta está muerto. Esto es lamentable, ya que es el único argumento aquí para que los FK mejoren el rendimiento.
Chris Moschini
1
@ChrisMoschini - No noté tu comentario hasta ahora. Como ha mencionado, el enlace está muerto, pero la esencia del mismo se menciona en el nuevo enlace (con detalles) que he publicado.
Lieven Keersmaekers
2
Enlace de Wayback Machine para Win! El artículo también se puede encontrar en SQLMag.com, aquí .
John Eisbrener
15

Una clave foránea es un concepto DBMS para garantizar la integridad de la base de datos.

Cualquier implicación / mejora en el rendimiento será específica de la tecnología de la base de datos que se utilice y es secundaria al propósito de una clave externa.

Es una buena práctica en SQL Server asegurarse de que todas las claves externas tengan al menos un índice no agrupado en ellas.

Espero que esto te aclare las cosas, pero no dudes en solicitar más detalles.

John Sansom
fuente
9
@Kenny Evitt si no tienes integridad, tus datos son inútiles. Me parece que se vende muy fácilmente.
HLGEM
@HLGEM Obtener un error 404 de vez en cuando sigue siendo bastante soportable. Tener un rendimiento excepcional a cambio utilizando recursos más baratos y sistemas menos complejos, ahora eso también se vende muy fácilmente. Quizás te interese el teorema CAP .
Daniel Dinnyes
8
@Daniel Dinnyes, la integridad de los datos no se trata de obtener un error 404. Se trata de tener datos utilizables. Se trata de no perder pedidos y datos financieros para informes, por ejemplo, debido a la incompetencia de los desarrolladores. NO HAY EXCUSA por no usar claves foráneas.
HLGEM
2
Estoy de acuerdo con HLGEM. Dejar que su código maneje la integridad no siempre es una buena idea. Los datos a menudo se usan para tomar decisiones, pero si los datos están dañados, entonces la decisión no será precisa.
lepe
1
"Las claves foráneas son una herramienta de integridad relacional". Utilice la palabra 'relacional' con cuidado. Las claves externas son un concepto de base de datos, una abreviatura de una restricción de integridad referencial. No son parte del modelo relacional. Supongo que cometiste un error tipográfico.
cuando el
4

Su mejor apuesta de rendimiento es usar Índices en los campos que usa con frecuencia. Si usa SQL Server, puede usar profiler para perfilar una base de datos específica y tomar el archivo que genera y usar el asistente de ajuste para recibir recomendaciones sobre dónde colocar sus índices. También me gusta usar el generador de perfiles para eliminar los procedimientos almacenados de larga ejecución, tengo una lista de los diez peores delincuentes que publico cada semana, hace que la gente sea honesta: D.

Al Katawazi
fuente
3

Puede usarlo para ayudar a que una consulta sea más eficiente. Le permite reestructurar las consultas en SQL Server para usar una combinación externa en lugar de una interna, lo que elimina la necesidad de tener que verificar si hay un valor nulo en la columna. No necesita poner ese calificador porque la relación de clave externa ya lo informa por usted.

Así que esto:

    select p.ProductId, p.Name, c.CategoryId, c.Name AS Category 
from Products p inner join ProductCategories c on p.CategoryId = c.CategoryIdwhere c.CategoryId = 1;

Se convierte en esto:

SELECT p.ProductId, p.Name, c.CategoryId, c.Name AS Category 
FROM ProductCategories c 
LEFT OUTER JOIN Products P ON
c.CategoryId = p.CategoryId 
WHERE c.CategoryId = 1;

Esto no necesariamente generará un gran rendimiento en consultas pequeñas, pero cuando las tablas crecen, puede ser más eficiente.

kemiller2002
fuente
3
Las combinaciones externas no solo son menos eficientes que las internas ( stackoverflow.com/a/2726683/155892 ), ahora sus consultas son engañosas: confía en la base de datos para convertir implícitamente sus combinaciones externas en combinaciones internas (restaurar el rendimiento) en lugar de hacerlo explícitamente
Mark Sowul
2

Para MySQL 5.7, definitivamente puede acelerar las consultas que involucran múltiples combinaciones increíblemente bien.

Solía ​​'explicar' para entender mi consulta y descubrí que me unía a 4-5 tablas, donde no se usaban claves. No hice nada más que agregar una clave externa a estas tablas y el resultado fue una reducción del 90% en el tiempo de carga. Las consultas que tomaron> 5s ahora toman 500ms o menos.

¡Esa es una mejora ENORME!

Y, como otros han mencionado, obtienes la ventaja adicional de garantizar la integridad relacional.

Más allá de esto, garantizar la integridad referencial también tiene sus propios beneficios de rendimiento. Tiene el efecto de segundo orden de garantizar que las tablas que tienen la clave externa estén 'actualizadas' con la tabla externa. Supongamos que tiene una tabla de usuarios y una tabla de comentarios, y está haciendo algunas estadísticas en la tabla de comentarios. Probablemente, si eliminas al usuario por completo, tampoco quieres sus comentarios.

Peter Bartlett
fuente
¿Las tablas tenían los índices necesarios para generar las claves externas antes de agregarlas?
George
1

Agregar una clave externa en la tabla no mejorará el rendimiento, simplemente diciendo que si está insertando un registro en una base de datos de la tabla ProductCategories intentará encontrar que la columna de clave externa tiene un valor que existe en el valor de la clave primaria de una tabla de productos, esta búsqueda, la operación es una sobrecarga en su base de datos cada vez que agrega una nueva entrada en la tabla ProductCategories. Por lo tanto, al agregar una clave externa no mejorará el rendimiento de su base de datos, pero se ocupará de la integridad de su base de datos. Sí, mejorará el rendimiento de su base de datos si está verificando la integridad utilizando una clave externa en lugar de ejecutar muchas consultas para verificar que el registro existe en la base de datos de su programa.

Pankaj Khairnar
fuente
0

No sé mucho sobre el servidor SQL, pero en el caso de Oracle, tener una columna de clave externa reduce el rendimiento de la carga de datos. Esto se debe a que la base de datos necesita verificar la integridad de los datos para cada inserción. Y sí, como ya se mencionó, tener un índice en la columna de clave externa es una buena práctica.

Shamik
fuente