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

Esquema de base de datos confuso (índice y restricciones)

Prefiero el segundo enfoque. Al usar números de ID sustitutos cuando no son lógicamente necesarios para la identificación, introduce más uniones obligatorias. Esto requiere que "persiga números de ID por toda la base de datos", que es el equivalente SQL a "perseguir punteros por toda la base de datos". Perseguir punteros era característico de IMS, una de las arquitecturas de bases de datos que el modelo relacional pretendía reemplazar. (IMS usa una arquitectura jerárquica). No tiene sentido reinventarlo hoy. (Aunque mucho de las personas hacen exactamente eso).

Si tiene, por ejemplo, cinco niveles de números de identificación sustitutos y desea el nombre de una persona, debe realizar cuatro combinaciones para obtenerlo. Usando el segundo enfoque, solo necesita una combinación. Si no desea escribir uniones de varias columnas, use CREAR VISTA y hágalo solo una vez.

El rendimiento es fácil de probar . Simplemente genere algunos millones de filas aleatorias utilizando su lenguaje de secuencias de comandos favorito y cárguelas en un servidor de prueba. No solo encontrará dónde se esconden sus problemas de rendimiento, encontrará todos los errores en su código CREATE TABLE. (Su código no funcionará tal cual). Obtenga información sobre EXPLAIN si aún no lo sabe.

En cuanto a la indexación , puede probar eso en las filas aleatorias que genera y carga. Un índice de varias columnas en (nombre, apellido) funcionará mejor si los usuarios siempre proporcionan un nombre. Pero muchos usuarios no harán eso, prefiriendo buscar por apellido en su lugar. Un índice de varias columnas en (first_name, last_name) no es efectivo para los usuarios que prefieren buscar por apellido. Puedes probar eso.

Solo por esa razón, la indexación de nombres y apellidos es generalmente más efectivo si hay dos índices separados, uno para el nombre y otro para el apellido.

¿Qué significa perseguir números de identificación significa?

El patrón de diseño tácito que subyace a esta pregunta es "Cada fila debe tener un número de identificación y todas las claves externas deben hacer referencia al número de identificación". En una base de datos SQL, en realidad es un antipatrón. Como regla general, cualquier patrón que le permita diseñar tablas sin pensar en las claves se debe considerar culpable hasta que se demuestre su inocencia; se debe suponer que es un antipatrón hasta que se demuestre que no lo es.

create table A (
 a_id integer primary key,
 a_1 varchar(15) not null unique,
 a_2 varchar(15) not null
);

create table B (
  b_id integer primary key
  a_id integer not null references A (a_id),
  b_1  varchar(10) not null,
  unique (a_id, b_1),
);

create table C (
  c_id integer primary key,
  b_id integer not null references B (b_id),
  c_1 char(3) not null,
  c_2 varchar(20) not null,
  unique (b_id, c_1)
);

create table D (
  d_id integer primary key,
  c_id integer not null references C (c_id),
  d_1 integer not null,
  d_2 varchar(15),
  unique (c_id, d_1)
);

Si necesita un informe sobre la tabla "D", y el informe necesita

  • columnas D.d_1 y D.d_2, y
  • columnas A.a_1 y A.a_2,

necesitas 3 uniones para llegar a él. (Pruébelo.) Está persiguiendo números de identificación. (Como perseguir punteros en IMS). La siguiente estructura es diferente.

create table A (
 a_1 varchar(15) primary key,
 a_2 varchar(15) not null
);

create table B (
  a_1 varchar(15) not null references A (a_1),
  b_1  varchar(10) not null,
  primary key (a_1, b_1),
);

create table C (
  a_1 varchar(15) not null,
  b_1 varchar(10) not null,
  c_1 char(3) not null,
  c_2 varchar(20) not null,
  primary key (a_1, b_1, c_1),
  foreign key (a_1, b_1) references B (a_1, b_1)
);

create table D (
  a_1 varchar(15) not null,
  b_1 varchar(10) not null,
  c_1 char(3) not null,
  d_1 integer not null,
  d_2 varchar(15),
  primary key (a_1, b_1, c_1, d_1),
  foreign key (a_1, b_1, c_1) references C (a_1, b_1, c_1)
);

Con esta estructura, el mismo informe necesita una única combinación.

select D.d_1, D.d_2, A.a_1, A.a_2
from D
inner join A on D.a_1 = A.a_1;