Pregunta

Existe un debate saludable entre claves sustitutas y naturales:

SO Post 1

SO Post 2

Mi opinión, que parece estar en línea con la mayoría (es una mayoría delgada), es que debe usar claves sustitutas a menos que una clave natural sea completamente obvia y garantice que no cambie. Entonces debes imponer la unicidad en la clave natural. Lo que significa claves sustitutas casi todo el tiempo.

Ejemplo de los dos enfoques, comenzando con una tabla de empresa:

1: clave sustituta: la tabla tiene un campo de ID que es el PK (y una identidad). Los nombres de las empresas deben ser únicos por estado, por lo que existe una restricción única allí.

2: Clave natural: la tabla usa CompanyName y State como PK; satisface tanto la PK como la unicidad.

Digamos que la PK de la empresa se usa en otras 10 tablas. Mi hipótesis, sin números que lo respalden, es que el enfoque de clave sustituta sería mucho más rápido aquí.

El único argumento convincente que he visto para la clave natural es para una tabla de muchos a muchos que usa las dos claves externas como clave natural. Creo que en ese caso tiene sentido. Pero puede meterse en problemas si necesita refactorizar; eso está fuera del alcance de esta publicación, creo.

¿Alguien ha visto un artículo que compara las diferencias de rendimiento en un conjunto de tablas que usan claves sustitutas vs. el mismo conjunto de tablas usando claves naturales ? Mirar alrededor de SO y Google no ha producido nada que valga la pena, solo una gran cantidad de elaboración de teorías.


Actualización importante : he comenzado a crear un conjunto de tablas de prueba que responden a esta pregunta. Se ve así:

  • PartNatural - tabla de piezas que usa el PartNumber único como PK
  • PartSurrogate - tabla de piezas que usa una ID (int, identidad) como PK y tiene un índice único en PartNumber
  • Planta - ID (int, identidad) como PK
  • Ingeniero - ID (int, identidad) como PK

Cada parte se une a una planta y cada instancia de una parte en una planta se une a un ingeniero. Si alguien tiene un problema con este banco de pruebas, ahora es el momento.

¿Fue útil?

Solución

¡Usa ambos! Las claves naturales evitan la corrupción de la base de datos (la inconsistencia podría ser una mejor palabra). Cuando el " derecho " la clave natural, (para eliminar filas duplicadas) funcionaría mal debido a la longitud o al número de columnas involucradas, para fines de rendimiento, se puede agregar una clave sustituta y usarla como claves foráneas en otras tablas en lugar de la clave natural. Pero la clave natural debe permanecer como una clave alternativa o índice único para evitar la corrupción de datos y garantizar la coherencia de la base de datos ...

Gran parte del hoohah (en el " debate " sobre este tema), puede deberse a lo que es una suposición falsa: que debe usar la Clave principal para combinaciones y claves foráneas en otras tablas. ESTO ES FALSO Puede usar CUALQUIER clave como destino para claves externas en otras tablas. Puede ser la clave primaria, una clave alternativa o cualquier índice único o restricción única. Y en cuanto a las uniones, puede usar cualquier cosa para una condición de unión, ¡ni siquiera tiene que ser una clave, un idex o incluso único! (aunque si no es único, obtendrá varias filas en el producto cartesiano que crea).

Otros consejos

Las claves naturales difieren de las claves sustitutas en valor, no tipo.

Cualquier tipo puede usarse para una clave sustituta, como un VARCHAR para el slug generado por el sistema o algo más.

Sin embargo, los tipos más utilizados para las claves sustitutas son INTEGER y RAW (16) (o cualquier tipo que utilice su RDBMS para GUID 's),

Comparar enteros sustitutos y enteros naturales (como SSN ) lleva exactamente el mismo tiempo.

La comparación de VARCHAR s toma en cuenta la intercalación y generalmente son más largos que los enteros, lo que los hace menos eficientes.

Comparar un conjunto de dos INTEGER es probablemente también menos eficiente que comparar un solo INTEGER .

En los tipos de datos de tamaño pequeño, esta diferencia es probablemente porcentajes de porcentajes del tiempo requerido para recuperar páginas, recorrer índices, trabar bases de datos, etc.

Y aquí están los números (en MySQL ):

CREATE TABLE aint (id INT NOT NULL PRIMARY KEY, value VARCHAR(100));
CREATE TABLE adouble (id1 INT NOT NULL, id2 INT NOT NULL, value VARCHAR(100), PRIMARY KEY (id1, id2));
CREATE TABLE bint (id INT NOT NULL PRIMARY KEY, aid INT NOT NULL);
CREATE TABLE bdouble (id INT NOT NULL PRIMARY KEY, aid1 INT NOT NULL, aid2 INT NOT NULL);

INSERT
INTO    aint
SELECT  id, RPAD('', FLOOR(RAND(20090804) * 100), '*')
FROM    t_source;

INSERT
INTO    bint
SELECT  id, id
FROM    aint;

INSERT
INTO    adouble
SELECT  id, id, value
FROM    aint;

INSERT
INTO    bdouble
SELECT  id, id, id
FROM    aint;

SELECT  SUM(LENGTH(value))
FROM    bint b
JOIN    aint a
ON      a.id = b.aid;

SELECT  SUM(LENGTH(value))
FROM    bdouble b
JOIN    adouble a
ON      (a.id1, a.id2) = (b.aid1, b.aid2);

t_source es solo una tabla ficticia con 1,000,000 filas.

aint y adouble , bint y bdouble contienen exactamente los mismos datos, excepto que aint tiene un entero como PRIMARY KEY , mientras que adouble tiene un par de dos enteros idénticos.

En mi máquina, ambas consultas se ejecutan durante 14.5 segundos, +/- 0.1 segundos

La diferencia de rendimiento, si la hay, está dentro del rango de fluctuaciones.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top