денормализация цепочечных таблиц базы данных mysql - PullRequest
2 голосов
/ 07 сентября 2011

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

Вот очень упрощенная модель вопроса.
Все таблицы на картинке соединены, и с нормализованной базой данных, чтобы получить, например, всех пользователей из определенной страны, я должен объединить все таблицы. Это примерно 250 стран примерно 12000 городов x 625000 регионов x? адреса х? пользователи ... Короче говоря, это много присоединений, что занимает много времени.

Что я хочу сделать, так это сделать country_id избыточным в таблице user, чтобы я мог получить тот же запрос без какого-либо присоединения.

Вопрос в том, что является наилучшей практикой для обеспечения согласованности в такой модели (кстати, с использованием MySql)?

Одним из способов и, возможно, самым быстрым является обеспечение согласованности на уровне приложения при вставке / обновлении / удалении данных.

Другое - это хранимые процедуры, в которых я действительно не вижу преимуществ. Они обеспечивают согласованность только при непосредственном вызове. Согласованность нарушается, если вы хотите внести некоторые изменения без процедур.

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

В любом случае, было бы предпочтительно обеспечить согласованность на уровне БД.

Любой совет?

Sample model

Ответы [ 3 ]

6 голосов
/ 11 сентября 2011

Все таблицы на картинке соединены, и с нормализованной базой данных, чтобы получить, например, всех пользователей из определенной страны, я должен объединить все таблицы.

У вас естьобъединить все таблицы, потому что вы используете суррогатные ключи (идентификационные номера), а не потому, что таблицы «нормализованы».Использование суррогатных ключей, таких как номера идентификаторов, не имеет ничего общего с нормализацией.

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

Самый простой способ увидеть, как это работает, - это начать с полных данных и работать в обратном направлении.Предположим, что все данные верны.

addr_id  street           street_num       region    city          country
--
1        Babukiaeeva      3a               10000     Zagreb        Croatia
2        Riva             16               51000     Rijeka        Croatia 
3        Andrije Hebranga 2-4              10000     Zagreb        Croatia
4        Andrijeviaeeva   2               110000     Zagreb        Croatia

Чтобы записать факты типа "Регион" 10000 "связан с городом" Загреб "в стране" Хорватия ", создайте новую таблицу и заполните ее изэтот запрос.

SELECT DISTINCT region, city, country from addresses;

Таблица будет выглядеть следующим образом.

Table: regions
Primary key: {region, city, country}

region   city      country
--
10000    Zagreb    Croatia
51000    Rijeka    Croatia
110000   Zagreb    Croatia

Затем установите ссылку на внешний ключ.

ALTER TABLE addresses 
ADD CONSTRAINT FOREIGN KEY        (region, city, country) 
               REFERENCES regions (region, city, country);

Чтобы записать факты типа «Город« Загреб »находится в стране« Хорватия »», создайте новую таблицу, заполните ее по этому запросу.

SELECT DISTINCT city, country from regions;

Таблица будет выглядеть следующим образомthis.

Table: cities
Primary key: {city, country}

city      country
--
Zagreb    Croatia
Rijeka    Croatia

Затем установите ссылку на внешний ключ.

ALTER TABLE regions 
ADD CONSTRAINT FOREIGN KEY       (city, country) 
               REFERENCES cities (city, country);

Повторите для стран.Таблицы стран, городов и регионов являются ключевыми, поэтому они находятся в 5NF.(У них не может быть никаких неключевых зависимостей, потому что у них нет неключевых столбцов.) В контексте большой области, как и во всей Европе, вполне вероятно, что таблица адресов также находится в 5NF.

С точки зрения производительности запросов, он, скорее всего, будет обходить вашу текущую схему, потому что он не нуждается в соединениях.

Возможно, вы захотите использовать ON UPDATE CASCADE;Вы можете не хотеть каскадно удалять, хотя.

1 голос
/ 21 октября 2011

Прежде всего - это действительно слишком медленно? Ты это пробовал? У вас есть приложение, в котором вы выгружаете всех пользователей (почему?) Или вы выбираете одного / нескольких пользователей время от времени. Поскольку у вас есть первичные ключи для всех этих идентификаторов, поиск не должен быть таким медленным, в конце концов, в фоновом режиме есть B-дерево.

Во-вторых, я бы не стал нормализовать на уровне улицы число , вы вряд ли получите от этого какую-либо выгоду, и вы, вероятно, в конечном итоге получите отношения 1: 1 между пользователем и адрес. Итак, перенесите свой номер улицы на клиента, или вы даже можете переместить всю таблицу адресов пользователю. Возможно, я бы переместил таблицу регионов также клиенту (это регионы городов?) И получил бы таблицы пользователей, городов и стран.

Тогда у вас будет два объединения, если это все еще слишком медленно, вы можете добавить избыточный ключ страны (или, поскольку мы денормализуем - название страны) в пользователях. Я бы использовал триггеры для поддержания целостности, точнее, вам придется написать: триггеры вставки и обновления (обновление необходимо запускать только при изменении regionId / cityId) и триггер обновления для страны (если иметь название страны в таблице пользователей) в маловероятном случае, если название страны изменится.

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

Наконец, поскольку вы не объяснили подробно природу и размер вашего (веб-приложения) приложения, просто напоминание о том, что вы можете также рассмотреть / включить другие технологии оптимизации вне реляционных баз данных (кэши, no-sql) дб и т. д.).

0 голосов
/ 07 сентября 2011

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

С другой стороны, большинство людей просто имеют адресную таблицу или (задыхаются!) Сохраняют информацию об адресе в пользовательской таблице. Сколько стран / городов вы планируете поддерживать, сколько пользователей?

...