Uso adecuado de tablas de búsqueda


25

Tengo problemas para descubrir exactamente cómo colocar buenos límites para cuándo y dónde usar tablas de búsqueda en una base de datos. La mayoría de las fuentes que he visto dicen que nunca puedo tener demasiadas pero, en algún momento, parece que la base de datos se dividirá en tantas partes que, si bien puede ser eficiente, ya no es manejable. Aquí hay un ejemplo de lo que estoy trabajando:

Digamos que tengo una tabla llamada Empleados:

ID  LName   FName   Gender  Position
1   Doe     John    Male    Manager
2   Doe     Jane    Female  Sales
3   Smith   John    Male    Sales

Imagine por un momento que los datos son más complejos y contienen cientos de filas. Lo más obvio que veo que podría moverse a una tabla de búsqueda sería Posición. Podría crear una tabla llamada Posiciones y pegar las claves externas de la tabla Posiciones en la tabla Empleados en la columna Posición.

ID  Position
1   Manager
2   Sales

Pero, ¿hasta qué punto puedo continuar dividiendo la información en tablas de búsqueda más pequeñas antes de que sea inmanejable? Podría crear una tabla de género y tener un 1 corresponde a Masculino y un 2 corresponde a Femenino en una tabla de búsqueda separada. Incluso podría poner LNames y FNames en tablas. Todas las entradas de "John" se reemplazan con una clave foránea de 1 que apunta a la tabla FName que dice que una ID de 1 corresponde a John. Sin embargo, si baja por esta madriguera de conejo, su tabla de Empleados se reduce a un desorden de claves externas:

ID  LName   FName   Gender  Position
1   1       1       1       1
2   1       2       2       2
3   2       1       1       2

Si bien esto podría o no ser más eficiente para que un servidor lo procese, esto es ciertamente ilegible para una persona normal que puede estar tratando de mantenerlo y hace que sea más difícil para un desarrollador de aplicaciones que intente acceder a él. Entonces, mi verdadera pregunta es ¿qué tan lejos está demasiado lejos? ¿Existen "mejores prácticas" para este tipo de cosas o un buen conjunto de pautas en alguna parte? No puedo encontrar ninguna información en línea que realmente establezca un buen conjunto de pautas utilizables para este problema en particular que estoy teniendo. El diseño de la base de datos es viejo para mí, pero el buen diseño de la base de datos es muy nuevo, por lo que las respuestas demasiado técnicas pueden estar sobre mi cabeza. ¡Cualquier ayuda sería apreciada!


55
Usar tablas de "búsqueda" es una cosa. Reemplazar texto con números de identificación es algo completamente diferente.
Mike Sherrill 'Cat Recall'

1
¡El género no siempre se puede fijar a 2 valores! Ahora que tenemos transiciones de género, es decir que una aplicación puede no necesitar categorías adicionales como 'hombre nacido ahora mujer' o 'mujer nacida ahora hombre'.

@ Mike, buen comentario!
Walter Mitty

En mi tienda, los pensadores pudieron detenerse después de que solo cuatro opciones, hombre, mujer, transgénero, no revelaran.
kevinsky

Respuestas:


22

Pero, ¿hasta qué punto puedo continuar dividiendo la información en tablas de búsqueda más pequeñas antes de que sea inmanejable? Podría crear una tabla de género y tener un 1 corresponde a Masculino y un 2 corresponde a Femenino en una tabla de búsqueda separada.

Estás mezclando dos temas diferentes. Un problema es el uso de una tabla de "búsqueda"; el otro es el uso de claves sustitutas (números de identificación).

Comience con esta tabla.

ID  LName   FName   Gender  Position
1   Doe     John    Male    Manager
2   Doe     Jane    Female  Sales
3   Smith   John    Male    Sales

Puede crear una tabla de "búsqueda" para posiciones como esta.

create table positions (
  pos_name varchar(10) primary key
);

insert into positions
select distinct position 
from employees;

alter table employees
add constraint emp_fk1
foreign key (position) 
  references positions (pos_name);

Su tabla original se ve exactamente igual que antes de crear la tabla de "búsqueda". Y la tabla de empleados no requiere uniones adicionales para obtener datos útiles y legibles para los humanos.

El uso de una tabla de "búsqueda" se reduce a esto: ¿Su aplicación necesita el control sobre los valores de entrada que proporciona una referencia de clave externa? Si es así, siempre puede usar una tabla de "búsqueda". (Independientemente de si utiliza una clave sustituta).

En algunos casos, podrá completar completamente esa tabla en tiempo de diseño. En otros casos, los usuarios deben poder agregar filas a esa tabla en tiempo de ejecución. (Y probablemente necesitará incluir algunos procesos administrativos para revisar nuevos datos). El género, que en realidad tiene un estándar ISO , se puede completar por completo en el momento del diseño. Los nombres de las calles para pedidos internacionales de productos en línea probablemente tengan que agregarse en tiempo de ejecución.


2
¡No sabía que podías hacer todo eso! La forma en que funciona su método es un poco hermosa. ¡Gracias!
Brad Turner

44
Me uní a DBA Stack Exchange solo para poder votar esta respuesta. Esto es hermoso y nunca se me ocurrió. ¡Gracias!
CindyH

Aprecio el método para llenar la tabla de búsqueda. Mi razón para leer esta pregunta fue para ver si habría un beneficio que no podría ver en una clave sustituta en mis tablas de búsqueda. Usted confirmó para mí que un solo campo de texto es tan bueno y útil como parece. Gracias.
Sinthia V

8

En su tabla de Empleados, solo buscaría "Posición" porque es un conjunto limitado de datos que pueden expandirse.

  • El género se describe a sí mismo (digamos Mo F), está limitado a 2 valores y se puede aplicar con una restricción CHECK. No agregará nuevos géneros (ignorando los errores de corrección política)
  • El primer nombre "John" no es parte de un conjunto limitado y restringido de datos: el conjunto potencial de datos es masivo hasta el punto de ser efectivamente ilimitado, por lo que no debería ser una búsqueda

Si desea agregar una nueva Posición, simplemente agregue una fila a la tabla de búsqueda. Esto también elimina las anomalías de modificación de datos, que es un punto de normalización.

Además, una vez que tiene un millón de empleados, es más eficiente almacenar tinyint PositionID que varchar.

Agreguemos una nueva columna "moneda de salario". Usaría una tabla de búsqueda aquí con una clave de CHF, GBP, EUR, USD, etc. No usaría una clave sustituta. Esto podría restringirse con una restricción CHECK como Gender, pero es un conjunto de datos limitado pero expandible como Position. Doy este ejemplo porque usaría la clave natural incluso si aparece en un millón de filas de datos de empleados a pesar de ser char (3) en lugar de tinyint

Entonces, para resumir, usas tablas de búsqueda

  1. donde tiene un conjunto de datos finito, pero ampliable en una columna
  2. donde no es autodescriptivo
  3. para evitar anomalías en la modificación de datos

1
Una posible razón para poner el género en una tabla de búsqueda es la localización.
a_horse_with_no_name

1
"Género ... (digamos M o F), limitado a 2 valores ... haciendo caso omiso de la corrección política" - Irónicamente, es la misma corrección política que parece aborrecer lo que hace que la gente "genere" incorrectamente (' Masculino ',' Femenino ') cuando significan "sexo" (' Masculino ',' Femenino '). Si el contexto es el género gramatical, generalmente hay más de dos valores. Si el contexto registra el sexo de un recién nacido, entonces hay al menos cuatro valores ("no se ha evaluado oficialmente" y "la evaluación oficial no fue concluyente"). PD: no quiero sonar duro, disfruté la ironía :)
día

44
@onedaywhen: el valor correcto para una columna llamada "Sexo" es "Sí, por favor". A menos que seas británico
gbn

El término "anomolias" está siendo mal utilizado aquí ya que el término tiene un significado particular diferente relacionado con la normalización, y el enlace es inapropiado.
philipxy

5

La respuesta es un "depende". No es muy satisfactorio, pero hay muchas influencias que empujan y tiran del diseño. Si tiene programadores de aplicaciones que diseñan la base de datos, una estructura como la que usted describe funciona para ellos porque el ORM oculta la complejidad. Te arrancarás el pelo cuando escribas informes y tendrás que unirte a diez mesas para obtener una dirección.

Diseño para el uso, uso previsto y probable uso futuro. Aquí es donde entra en juego su conocimiento del proceso de negocios. Si está diseñando una base de datos para un negocio veterinario, existen suposiciones razonables sobre el tamaño, el uso y las instrucciones en la funcionalidad que serán bastante diferentes a las de una nueva empresa de alta tecnología.

Para reutilizar una cita favorita

"Un hombre sabio me dijo una vez" normalizar hasta que duela, desnormalizar hasta que funcione ".

En algún lugar allí está el punto dulce. Mi experiencia ha sido que tener una identificación de clave en más de una tabla no es un delito tan grave como algunos piensan si nunca cambias las claves principales.

Tome este ejemplo abreviado de tablas altamente normalizadas de un sistema real

CREATE TABLE PROPERTY
(ID                          NUMBER(9)           NOT NULL);

CREATE TABLE PROPERTY_TYPE
(ID                          NUMBER(9)           NOT NULL);

CREATE TABLE PROPERTY_LOCALE 
PROPERTY_ID                  NUMBER(9)           NOT NULL,
(LOCALE_ID                   NUMBER(9)           NOT NULL,  --language 
VALUE                        VARCHAR2(200)       NOT NULL);

CREATE TABLE PROPERTY_DEPENDENCY
(PROPERTY_ID                 NUMBER(9)           NOT NULL,
 PARENT_PROPERTY_ID          NUMBER(9)                   ,
 PROPERTY_TYPE_ID            NUMBER(9)           NOT NULL);

Estas tablas configuran una lista vinculada de propiedades individuales y propiedades primarias y secundarias y se usan aquí

  CREATE TABLE CASE_PROPERTY
  (ID                        NUMBER(9)           NOT NULL,
  PARENT_ID                  NUMBER(9),
  CASE_ID                    NUMBER(9)           NOT NULL,
  PROPERTY_ID                NUMBER(9),
  PROPERTY_TYPE_ID           NUMBER(9)           NOT NULL);

Esto se ve bien: obtenga todos los casos con un property_id en una selección

Obtengamos una lista para elegir

 Select pl.value, pd.property_id
 from property_locale pl, property_dependency pd
 where pl.property_id = pd.property_id
 and pd.property_type_id = 2;  --example number

Ahora intente seleccionar todas las propiedades de un caso si tiene propiedades_tipos de 3 y 4 y 5, o no ...

SELECT   cp2.case_id,
         (SELECT   pl.VALUE
            FROM   case_property cp, property_locale pl
           WHERE       cp.property_id = pl.property_id
                   AND CP.PROPERTY_TYPE_ID = 2
                   AND pl.locale_id = 2
                   AND cp.case_id = cp2.case_id)
            AS VALUE1,
         (SELECT   pl.VALUE
            FROM   case_property cp, property_locale pl
           WHERE       cp.property_id = pl.property_id
                   AND CP.PROPERTY_TYPE_ID = 34
                   AND pl.locale_id = 2
                   AND cp.case_id = cp2.case_id)
            AS VALUE2,
         (SELECT   pl.VALUE
            FROM   case_property cp, property_locale pl
           WHERE       cp.property_id = pl.property_id
                   AND CP.PROPERTY_TYPE_ID = 4
                   AND pl.locale_id = 2
                   AND cp.case_id = cp2.case_id)
            AS VALUE3
  FROM   case_property cp2
 WHERE   cp2.case_id = 10293  

Esto duele ... incluso cuando usas formas más elegantes de lidiar con esto. Sin embargo, agregue un poco de normalización separando las propiedades para las que un caso solo tendrá un property_id y esto podría ser mucho mejor.

Para saber cuándo tiene demasiadas tablas o si no hay suficientes, intente consultar la base de datos con preguntas sobre la aplicación, se utilizará un informe y un análisis anual.


55
Los números de identificación no tienen nada que ver con la normalización. El hecho de que cada tabla tenga un número de identificación no significa que esté en 5NF, o incluso en 3NF. Simplemente significa que tiene que hacer muchas uniones para obtener datos utilizables de esa tabla.
Mike Sherrill 'Cat Recall'
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.