Правильне використання таблиць пошуку


25

У мене виникають труднощі з розумінням того, як саме розмістити хороші межі для того, коли і де використовувати таблиці пошуку в базі даних. Більшість джерел, на які я звернувся, говорять про те, що я ніколи не можу мати занадто багато, але, в якийсь момент, здається, що база даних буде розбита на стільки частин, що, хоча це може бути ефективною, вона вже не керується. Ось спільний приклад того, з чим я працюю:

Скажімо, у мене є таблиця під назвою Співробітники:

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

Прикиньте на мить, що дані складніші і містять сотні рядків. Найбільш очевидно, що я бачу, що це може бути переміщено до таблиці пошуку, це позиція. Я міг би створити таблицю під назвою "Позиції" і вставити зовнішні ключі з таблиці "Позиції" в таблицю "Співробітники" в стовпці "Позиція".

ID  Position
1   Manager
2   Sales

Але як далеко я можу продовжувати розбивати інформацію на менші таблиці пошуку, перш ніж вона стане некерованою? Я можу створити гендерну таблицю і мати окрему таблицю пошуку 1, що відповідає чоловікові, і 2 для жінки. Я навіть міг помістити LNames та FNames у таблиці. Усі записи "Джон" замінюються зовнішнім ключем 1, який вказує на таблицю FName, в якій зазначено, що ІД відповідає 1. Якщо ви опуститеся в цю кролячу нору занадто далеко, як це, то ваш стіл працівників потім зменшується до безладу сторонніх ключів:

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

Хоча це може бути або не бути більш ефективним для обробки сервера, це звичайно не читається для звичайної людини, яка, можливо, намагається підтримувати його і ускладнює розробника програми, який намагається отримати доступ до нього. Отже, моє справжнє запитання - наскільки далеко далеко? Чи є десь "найкращі практики" для подібних речей чи хороший набір інструкцій? Я не можу знайти будь-яку інформацію в Інтернеті, яка б справді привела в дію хороший корисний набір вказівок щодо цього конкретного питання, яке я маю. Дизайн бази даних для мене старий капелюх, але ДОБРИЙ дизайн баз даних є дуже новим, тому надмірно технічні відповіді можуть бути над головою. Будь-яка допомога буде вдячна!


5
Використання таблиць "пошуку" - одне. Заміна тексту на ідентифікаційні номери - це зовсім інша річ.
Майк Шеррілл 'Відкликання котів'

1
Стать не завжди може бути встановлена ​​на 2 значення! Тепер, коли ми маємо гендерні переходи, хто може сказати, що додатку можуть не знадобитися додаткові категорії, такі як "народжений чоловік зараз жінка" або "народжена жінка зараз чоловік".

@Mike, хороший коментар!
Вальтер Мітті

У моєму магазині мислителі змогли зупинитись лише після чотирьох виборів: чоловіки, жінки, трансгендери не розголошували.
кевінський

Відповіді:


22

Але як далеко я можу продовжувати розбивати інформацію на менші таблиці пошуку, перш ніж вона стане некерованою? Я можу створити гендерну таблицю і мати 1 відповідну чоловікові та 2 відповідність жінці в окремій таблиці пошуку.

Ви змішуєте дві різні проблеми. Одне питання - використання таблиці "пошуку"; інше - використання сурогатних ключів (ідентифікаційних номерів).

Почніть з цієї таблиці.

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

Ви можете створити таблицю "пошуку" для таких позицій.

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);

Ваша оригінальна таблиця виглядає точно так, як це було зроблено перед створенням таблиці "пошуку". Таблиця співробітників не потребує додаткових приєднань, щоб отримати корисні, зрозумілі для людини дані.

Використання таблиці "пошук" зводиться до цього: Чи потрібен вашій програмі контроль над вхідними значеннями, які надає посилання на іноземний ключ? Якщо так, то ви завжди можете використовувати таблицю "пошуку". (Незалежно від того, використовує він сурогатний ключ.)

У деяких випадках ви зможете повністю заповнити цю таблицю під час проектування. В інших випадках користувачі повинні мати можливість додавати рядки до цієї таблиці під час виконання. (І, ймовірно, вам потрібно буде включити деякі адміністративні процеси для перегляду нових даних.) Стать, яка фактично має стандарт ISO , може бути повністю заселена під час проектування. Назви вулиць для міжнародних онлайн-замовлень товарів, ймовірно, потрібно додати під час виконання.


2
Я не знав, що ти можеш все це зробити! Те, як працює ваш метод, виглядає якось красиво. Дякую!
Бред Тернер

4
Я приєднався до біржі стеків DBA просто для того, щоб я міг проголосувати цю відповідь. Це прекрасно і мені ніколи не приходило в голову. Спасибі!
CindyH

Я ціную метод заповнення таблиці пошуку. Моя причина для читання цього питання полягала в тому, щоб побачити, чи не буде користі, яку я не міг бачити сурогатним ключем на своїх таблицях пошуку. Ви підтвердили для мене, що одне текстове поле настільки ж добре і корисне, як і з'являється. Дякую.
Sinthia V

8

У вашій таблиці співробітників у мене буде пошук лише "Позиція", оскільки це обмежений набір даних, який може розширюватися.

  • Стать самоописується (скажіть Mчи F), обмежується двома значеннями, і може бути застосована з обмеженням ПЕРЕВІРИТИ. Ви не будете додавати нові гендери (ігноруючи політичну коректність)
  • Ім'я "Джон" не входить до обмеженого, обмеженого набору даних: потенційний набір даних є масовим до фактично необмеженого, тому він не повинен шукати

Якщо ви хочете додати нову позицію, просто додайте рядок до таблиці пошуку. Це також усуває аномалії модифікації даних, що є одним із пунктів нормалізації

Крім того, якщо у вас є мільйон співробітників, тоді ефективніше зберігати крихітний PositionID, ніж варчар.

Додамо нову колонку "валюта зарплати". Я б тут використовував таблицю пошуку з ключем CHF, GBP, EUR, USD тощо: я б не використовував сурогатний ключ. Це може бути обмежено обмеженням CHECK типу гендер, але це обмежений, але розширюваний набір даних, наприклад, Position. Я наводжу цей приклад, тому що я використовував би природний ключ, навіть якщо він відображається у мільйонах рядків даних про співробітників, незважаючи на те, що він char (3), а не крихітний

Отже, підсумовуючи, ви використовуєте таблиці пошуку

  1. де у вас є кінцеві, але розширювані набір даних у стовпці
  2. де це не самоопис
  3. щоб уникнути аномалій модифікації даних

1
Однією з можливих причин включити гендер у таблицю пошуку - це локалізація.
a_horse_with_no_name

1
"Стать ... (скажімо, M або F), обмежена двома значеннями ... ігнорування політичної коректності, що висловлюється" - Як не дивно, саме ця політична коректність, яку ви, здається, огидаєте, викликає в людей неправильно "гендер" (" Чоловічий "," жіночий "), коли вони означають" секс "(" Чоловік "," Жінка "). Якщо контекст є граматичним гендером, то зазвичай існує більше двох значень. Якщо контекст записує стать новонародженого, то принаймні чотири значення ("офіційно не було оцінено" і "офіційна оцінка була непереконливою"). ps Я не хочу звучати суворо, мені сподобалася іронія :)
onedaywhen

4
@onedaywhen: правильне значення для стовпця під назвою "Секс" - "Так, будь ласка". Якщо ви не британець
gbn

Термін "аномолії" тут зловживається, оскільки термін має інше особливе значення, пов'язане з нормалізацією, а посилання є невідповідним.
philipxy

5

Відповідь - "це залежить". Не дуже задовольняє, але є багато впливів, що підштовхують і тягнуть дизайн. Якщо у вас є програмісти програм, які проектують базу даних, така структура, як ви описуєте, працює для них, оскільки ORM приховує складність. Ви будете витягувати волосся, коли будете писати звіти, і вам доведеться приєднатися до десяти таблиць, щоб отримати адресу.

Дизайн для використання, цільового призначення та ймовірного майбутнього використання. Тут ви знайдете свої знання про бізнес-процес. Якщо ви розробляєте базу даних для ветеринарного бізнесу, є обґрунтовані припущення щодо розміру, використання та вказівок у функціональності, які будуть зовсім іншими, ніж запуск високотехнологічних технологій.

Щоб повторно використовувати улюблену цитату

"Мудрець одного разу сказав мені:" нормалізуйся, поки не болить, денормалізуй, поки це не працює ".

Десь там є мила пляма. Мій досвід показав, що наявність ідентифікатора ключа в більш ніж одній таблиці не є таким серйозним злочином, як деякі думають, якщо ви ніколи не поміняєте первинні ключі.

Візьмемо цей скорочений приклад сильно нормалізованих таблиць з реальної системи

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);

Ці таблиці встановлюють пов'язаний список одинакових властивостей та батьківських дочірніх властивостей, і вони тут використовуються

  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);

Це виглядає чудово: отримайте всі випадки з property_id за один вибір

Давайте отримаємо список, з якого можна вибрати

 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

Тепер спробуйте вибрати всі властивості випадку, якщо він має типи властивостей 3 та 4 та 5, чи ні ...

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  

Це просто боляче ... навіть коли ви використовуєте більш елегантні способи боротьби з цим. Однак додайте трохи нормування, викресливши властивості, для яких у випадку буде лише одна властивість_id, і це може бути набагато кращим.

Щоб дізнатись, коли у вас занадто багато таблиць чи недостатньо, спробуйте запитати базу даних із запитаннями, які використовуватимуть додаток, звіт та аналіз року.


5
Ідентифікаційні номери не мають нічого спільного з нормалізацією. Тільки тому, що в кожній таблиці є ідентифікаційний номер, це не означає, що це в 5NF або навіть у 3NF. Це просто означає, що вам потрібно зробити багато приєднань, щоб отримати корисні дані з цієї таблиці.
Майк Шеррілл 'Відкликання котів'
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.