2009-07-28 2 views
4

Я разрабатываю приложение базы данных, в котором хранятся простые контактные данные (имя/фамилия и т. Д.), А также я должен хранить номера телефонов. Помимо телефонных номеров, я должен хранить то, за что они предназначены (мобильный, бизнес и т. Д.) И, возможно, дополнительный комментарий для каждого.Нормализовать или Денормализовать: сохранить контактные данные (номера телефонов) в отдельной таблице? Результаты поиска?

Мой первый подход состоял в нормализации и сохранении номеров телефонов в отдельной таблице, так что у меня есть мои «Контакты» и моя таблица «PhoneNumbers». В таблице номера телефонов будет выглядеть так:

Id int PK 
ContactId int FK<->Contacts.Id 
PhoneNumber nvarchar(22) 
Description nvarchar(100) 

Однако было бы сделать вещи намного проще и сохранить SQL Регистрация при извлечении, если я просто хранить эту информацию как часть записи каждого контакта (при условии, что я ограничиваю общее # номеров телефонов, которые можно сохранить, чтобы сказать 4 числа).

Однако, я в конечном итоге с «уродливой» структуры, как это:

PhoneNumber1 nvarchar(22) 
Description1 nvarchar(100) 
PhoneNumber2 nvarchar(22) 
Description2 nvarchar(100) 

и т.д. и т.п.

Это выглядит дилетантским для меня, но здесь преимущества я вижу:

1) В ASP.NET MVC я могу просто прикрепить входные текстовые поля к свойствам объекта LINQ, и я покончил с добавлением и обновлением записей.

2) Нет необходимости использовать SQL для получения информации.

К сожалению, я не очень хорошо разбираюсь в таких проблемах, как проблемы с шириной таблицы (я читал, что это может вызвать проблемы, если оно слишком велико или слишком много столбцов и что проблемы с производительностью возникают?), А затем это будет означать, что когда I поиск для номера телефона Мне нужно было бы посмотреть 4 поля вместо 1, если бы я сохранил его в отдельной таблице.

Мое приложение имеет около 80% поиска/поиска данных, поэтому эффективность поиска является важным фактором.

Я ценю вашу помощь в поиске правильного пути для этого. Разделить таблицу или сохранить все в одном? Спасибо!

+0

Я поставил ответ ниже, но один дополнительный совет - увеличить первоначальную производительность и прочитать о создании соответствующих индексов в соответствии с вашей настройкой LINQ to SQL. Кроме того, мониторинг производительности БД является продолжающейся вещью, поскольку таблицы растут и, возможно, меняются функциональные возможности, лучше регулярно анализировать производительность БД, а не ждать, пока пользователи будут жаловаться, что их опыт страдает. – MadMurf

+0

это отличное решение ... пока вам не понадобится 5 телефонных номеров вместо 4. Нормализовать для обслуживания. –

ответ

9

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

Contacts: 
    ID (Primary Key) 
    Name 
    Job Title 

Phone Number Categories: 
    ID (Primary key) 
    Name 

Phone Numbers: 
    ID (Primary Key) 
    Category_ID (Foreign Key -> Phone Number Categories.ID) 
    Contact_ID (Foreign Key -> Contacts.ID) 
    Phone Number 

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

+0

Я согласен с @Mike, как уже упоминалось ниже, но сделаем это еще дальше и сделаем таблицу категорий номеров телефонов, предложенную в его ответном роде, чтобы вы могли повторно использовать ее для других полей кода/описания в другом месте вашего приложения. – MadMurf

+0

Привет @Mike Trpcic Я использую аналогичную таблицу в MYSQL. Я пытаюсь получить данные, например, Contact ID = 1 Как я буду денормализовать несколько телефонных номеров в виде столбцов. Не могли бы вы помочь с примером Select Statement? – harishannam

+0

@Mike Trpcic, как бы вы добавили настройки конфиденциальности? Еще один стол? –

6

Возможно, сейчас все в порядке, но что происходит, когда кому-то нужен пятый номер телефона? Продолжаете ли вы добавлять все больше и больше полей?

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

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

Возвращаясь к первому вопросу о добавлении большего количества телефонных номеров в будущем - если вы добавите больше номеров, вам нужно будет исправить, вероятно, каждый запрос/бит логики/формы, который работает с данными, которые нужно делать с телефонными номерами.

+0

Число телефонных номеров не является проблемой. Независимо от того, занимаюсь ли я 4 или 6, проблема остается прежней, и для меня все нормально, что разумно. Ваш второй комментарий - это то, о чем я тоже думаю (см. Часть о поиске в моем вопросе). Мне нужно было бы посмотреть на 4 поля. Я хотел бы знать, как страдает производительность, когда я это делаю. Тем более, что они должны были бы как-то полностью индексироваться в тексте (я не могу ограничивать цифры в формате США или что-то в этом роде.) – Alex

+0

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

+0

Все люди и их мобильные номера будут решены с использованием кода, предложенного мной в моем ответе ниже. Вы можете оптимизировать свои индексы на основе поисков, которые вы планируете предлагать. Ознакомьтесь с http://sqlblog.com/blogs/jonathan_kehayias/archive/2009/02/17/linq-to-sql-the-ongo-developer-dba-debate.aspx и ссылками на этой странице для получения рекомендаций. – MadMurf

0

Как насчет поля XML в таблице контактов? Это устраняет сложность другой таблицы.

(Пожалуйста, поправьте меня, если это плохая идея, я никогда не работал с полями XML до)

+0

Обычно вы хотите, чтобы какой-либо один столбец отслеживал только одно свойство. – Rake36

4

Я за нормированный подход. Что, если вы решили, что хотите добавить столбец «Расширение» для телефонных номеров? Вам нужно будет создать столбцы «Extension1», «Extension2», «Extension3» и т. Д. Это может стать довольно утомительным для поддержания в какой-то момент.

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

1

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

Как для нормализованной таблицы Я хотел бы добавить поле типа или кода, так что вы можете сказать ID Home, Home 1, дом 2, Бизнес, автобус 1, автобус 2, Mobile, Mob1 и т.д ...

Id int PK 
ContactId int FK<->Contacts.Id 
Code char(5) 
PhoneNumber nvarchar(22) 
Description nvarchar(100) 

И хранить этот тип в отдельной таблице с сказать другое описание кода/код информация

Мы, как правило, имеют кодовую таблицу группы с информацией, такие как

CODE_GROUP, CODE DESC 
ST   State 
PH   Phone Number 
AD   Address Type 

И таблице CODE с

CODE_ID, CODE_GROUP, DESCRIPTION 
MB1  PH   Mobile One 
MB2  PH   Mobile Two 
NSW  ST   New South Wales 
etc... 

Вы можете расширить это, чтобы иметь длинное описание, короткое DESC, заказ, фильтрация и т.д.

3

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

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

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

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

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

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

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