Таблица с единственным идентификатором и многими таблицами соединений

71
8

Я пытаюсь создать базу данных как можно более масштабируемую, поэтому я тестирую концепцию с помощью простого сценария.

Допустим, у меня есть contact стол. Обычно контакт имеет address, phone number mobile number и email address.

Эта таблица может содержать одну таблицу. Однако, если контакт имеет более чем одну из этих деталей? Мое решение состояло бы в том, чтобы использовать таблицы соединений так:

contact -* contact_address *- address
contact -* contact_phone *- phone
contact -* contact_mobile *- phone
contact -* contact_emailaddress *- emailaddress

Это позволит мне получить всю информацию о контакте. Кроме того, таблицы address, phone и электронной emailaddress становятся банками данных, служащими для целей анализа, чтобы просто повторно использовать данные.

Тем не менее, я пока не знаю, каковы последствия этого для производительности, и является ли это хорошей практикой, главным образом потому, что таблица contact будет содержать только id и ничего другого.

Одно замечание состоит в том, что это использует doctrine2 с symfony2, поэтому запись длинных запросов не будет проблемой, мои основные проблемы - это выше, это привело к переходу с одной таблицы на восемь, а контакты - это только одна область, в которой мне нужно использовать шаблон это.

спросил(а) 2013-05-09T13:08:00+04:00 7 лет, 5 месяцев назад
1
Решение
57

Это отлично подходит для использования, вы не должны беспокоиться.

Единственная проблема заключается в том, если вы разрешаете Doctrine для ленивых отношений. Пример: если вы

$contact = $repository->find(1) ;

и позже в шаблонах вы делаете что-то вроде

{% for email in contact.emails %}
{{ email.address }}
{% endfor %}

этот код вызовет другой оператор SELECT. Теперь, если вы показываете, пусть говорят 10 контактов на страницу, это означает, что будут выполнены еще 10 запросов.

Сделайте математику, если вы показываете другие вещи, такие как адрес или номера телефонов.

Чтобы избежать этой ленивой нагрузки, вам нужно ПРИСОЕДИНИТЬ их в своем запросе. подобно

// ContactRepository

public function findForSomePage()
{
return $this->createQueryBuilder("o")
->leftJoin("o.addresses", "a")->addSelect("a")
.... other joins ...
->getQuery()
->getResult()
}

Теперь все, что вам нужно для отображения, выбирается в течение одного запроса.

ответил(а) 2013-05-11T17:17:00+04:00 7 лет, 5 месяцев назад
41

Используйте наследование таблицы.

Пример одиночного стола:

create table address_type(
id char(1) primary key,
description text not null unique
);

insert into address_type values
('t', 'Telephone Number'),
('e', 'E-mail Address'),
('m', 'Mailing Address'),
('w', 'Web Address');

create table address_role(
id char(1) primary key,
description text not null unique
);

insert into address_role values
('f','Fax'),
('m','Mobile'),
('h','Home'),
('w', 'Work');

create table address(
id serial primary key,
type char(1) not null references address_type(id),
telephone_number varchar(15) null,
email_address varchar(320) null,
web_address varchar(2083) null,
suite_or_apartment text null,
city_id bigint null references city(id),
postal_area_id bigint null references postal_area(id)
);

create table party(
id serial primary key,
name varchar(255) not null
);

create table party_address(
party_id bigint not null references party(id),
address_id bigint not null references address(id),
from_date date not null default current_date,
to_date date null,
role char(1) null references address_role(id),
telephone_extension varchar(5) null,
primary key (party_id, address_id, from_date)
);

ответил(а) 2013-05-11T22:07:00+04:00 7 лет, 5 месяцев назад
42

Если контакт имеет более одного адреса, вы не использовали бы таблицу соединений, вы просто использовали бы внешний ключ от адреса для контакта.

Я ожидаю, что этот проект, скорее всего, будет более результативным, хотя есть много факторов, которые следует учитывать.


Если адрес может быть прикреплен к нескольким контактам, а контакт может иметь более одного адреса, тогда вы должны использовать таблицу соединений.

ответил(а) 2013-05-09T13:13:00+04:00 7 лет, 5 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема