Правильное использование таблиц поиска
-
16-10-2019 - |
Вопрос
У меня проблемы с выяснением, как точно разместить хорошие границы, когда и где использовать таблицы поиска в базе данных. Большинство источников, на которых я смотрел, говорят, что у меня никогда не будет слишком много, но в какой -то момент кажется, что база данных будет разбита на столько частей, что, хотя она может быть эффективной, она больше не подлежит управлению. Вот пример того, с чем я работаю:
Допустим, у меня есть стол под названием сотрудники:
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 соответствуют женщине в отдельной таблице поиска. Я мог бы даже поместить lname и fnames в столы. Все записи «Джона» заменяются иностранным ключом 1, который указывает на таблицу Fname, в которой говорится, что идентификатор 1 соответствует Джону. Если вы зайдете в эту кроличье дыру слишком далеко, однако, столик ваших сотрудников превращается в беспорядок иностранных ключей:
ID LName FName Gender Position
1 1 1 1 1
2 1 2 2 2
3 2 1 1 2
Хотя это может или не может быть более эффективным для обработки сервера, это, безусловно, нечитаемо для нормального человека, который может пытаться его поддерживать, и затрудняет разработчик приложений, пытающегося получить к нему доступ. Итак, мой настоящий вопрос в том, как далеко слишком далеко? Существуют ли «лучшие практики» для такого рода вещи или хороший набор руководящих принципов? Я не могу найти никакой информации в Интернете, которая действительно прижимает хороший, полезный набор руководящих принципов для этой конкретной проблемы, который у меня есть. Дизайн базы данных для меня старая шляпа, но хороший дизайн базы данных очень новый, поэтому чрезмерно технические ответы могут быть над моей головой. Любая помощь будет оценена!
Решение
Но как далеко я могу продолжать разбить информацию на меньшие таблицы поиска, прежде чем она станет неуправляемой? Я мог бы создать гендерную таблицу и иметь 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, может быть полностью заполнено во время дизайна. Названия улиц для международных онлайн -заказов продуктов, вероятно, должны быть добавлены во время выполнения.
Другие советы
В таблице ваших сотрудников я только искал «позицию», потому что это ограниченный набор данных, которые могут расширяться.
- Пол самостоятельно описывает (скажем
M
или жеF
), ограниченным 2 значениями, и может быть обеспечено с ограничением проверки. Вы не добавите новые полов (игнорируя коллока политкорректности) - Первое имя «Джон» не является частью ограниченного, ограниченного набора данных: потенциальный набор данных массивен до такой степени безграничной, поэтому он не должен быть поиском
Если вы хотите добавить новую позицию, вы просто добавляете строку в таблицу поиска. Это также удаляется Аномалии модификации данных который является одной точкой нормализации
Кроме того, когда у вас будет миллион сотрудников, то более эффективно хранить TinyInt PosipId, чем Varchar.
Давайте добавим новую колонку «валюта зарплаты». Я использовал бы здесь таблицу поиска с ключом CHF, GBP, EUR, USD и т. Д. Я бы не использовал суррогатный ключ. Это может быть ограничено ограничением проверки, таким как пол, но это ограниченный, но расширяемый набор данных, таких как позиция. Я привожу этот пример из -за того, что я бы использовал естественный ключ, даже если он появляется в миллионе рядов данных сотрудника, несмотря на то, что он был Char (3), а не Tinyint
Итак, подвести итоги, вы используете таблицы поиска
- где у вас есть конечные, но расширяемые данные настройки в столбце
- где не описывается
- избегать Аномалии модификации данных
Ответ - «это зависит». Не очень удовлетворяет, но есть много влияний, толкающих и тянущих дизайна. Если у вас есть программисты приложений, разрабатывающие базу данных, структура, как вы описываете, работает для них, потому что 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 и 4 или нет ...
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
Это просто больно ... даже когда вы используете более элегантные способы справиться с этим. Тем не менее, добавьте немного нормализации DE, разрывая свойства, которые в случае будет только одно Property_ID, и это может быть намного лучше.
Чтобы выяснить, когда у вас слишком много таблиц или недостаточно попробуйте запросить базу данных с вопросами, которые приложение и анализ из года в год будет использовать.