Нормализация очень большой таблицы

Я сталкиваюсь со следующей проблемой. У меня очень большой стол. Этот стол является наследием людей, которые ранее работали над проектом. Таблица находится в MS SQL Server.

Таблица имеет следующие свойства:

  1. он имеет около 300 столбцов. Все они имеют «текстовый» тип, но некоторые из них в конечном итоге должны представлять другие типы (например, целое число или дату и время). Поэтому перед их использованием необходимо преобразовать эти текстовые значения в соответствующие типы.
  2. таблица имеет более 100 миллионов строк. Место для таблицы скоро достигнет 1 терабайта
  3. в таблице нет индексов
  4. таблица не имеет каких-либо реализованных механизмов секционирования.

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

Одной из наиболее важных особенностей таблицы является то, что те поля, которые являются чисто текстовыми (т. е. их не нужно преобразовывать в другой тип), обычно имеют часто повторяющиеся значения. Таким образом, фактическое разнообразие значений в данном столбце находится в диапазоне от 5 до 30 различных значений. Это наводит на мысль сделать нормализацию: для каждого такого текстового столбца я создам дополнительную таблицу со списком всех различных значений, которые могут появиться в этом столбце, затем я создам первичный ключ (tinyint) в этой дополнительной таблице и затем будет использовать соответствующий внешний ключ в исходной таблице вместо сохранения этих текстовых значений в исходной таблице. Затем я добавлю индекс к этому столбцу внешнего ключа. Количество столбцов, которые будут обработаны таким образом, составляет около 100.

Возникают следующие вопросы:

  1. действительно ли эта нормализация увеличит скорость запросов, налагающих условия на некоторые из этих 100 полей? Если мы забудем о размере, необходимом для хранения этих столбцов, будет ли какое-либо увеличение производительности из-за замены исходных текстовых столбцов столбцами tinyint? Если я не буду выполнять нормализацию и просто поставлю индекс для этих исходных текстовых столбцов, будет ли производительность такой же, как для индекса для запланированного столбца tinyint?
  2. Если я выполню описанную нормализацию, то для создания представления, показывающего текстовые значения, потребуется соединить мою основную таблицу с примерно 100 дополнительными таблицами. Положительным моментом является то, что эти объединения я буду делать для пар "первичный ключ"="внешний ключ". Но все же достаточно большое количество таблиц должно быть объединено. Вот вопрос: не будет ли производительность запросов к этому представлению по сравнению с производительностью запросов к исходной ненормализованной таблице хуже? Действительно ли SQL Server Optimizer сможет оптимизировать запрос таким образом, чтобы воспользоваться преимуществами нормализации?

Извините за такой длинный текст.

Спасибо за каждый комментарий!

PS Я создал связанный вопрос о присоединении к 100 таблицам; Объединение 100 таблиц


person iCoffee    schedule 07.02.2013    source источник
comment
Вам понадобится пара галлонов кофе, чтобы исправить это.   -  person Kermit    schedule 07.02.2013
comment
Первый вопрос, который вы должны задать: есть ли у таблицы первичный ключ? И 2-й, если нет, какой столбец (комбинация) можно использовать в качестве первичного ключа? Затем вы можете продолжить поиск зависимостей и нормализацию. Идея справочных таблиц ценна, да.   -  person ypercubeᵀᴹ    schedule 07.02.2013
comment
Вы упомянули, что люди больше не запрашивают таблицу, поэтому вы хотите решить какую-либо проблему? Я имею в виду, в настоящее время трудно сделать резервную копию БД из-за нехватки места, или вам действительно нужны отчеты из этой таблицы и т. д.? Пожалуйста, сообщите нам, как вы хотите использовать эту таблицу и каковы ваши цели рефакторинга.   -  person Tim Lehner    schedule 07.02.2013
comment
@iCoffee - Подтвердите, что информация имеет ценность для ваших пользователей, прежде чем браться за такую ​​задачу - IMO.   -  person rfusca    schedule 07.02.2013
comment
Информация чрезвычайно важна для пользователей, и они очень расстроены тем, что не могут эффективно выполнять запросы к таблице. Моя задача — реструктурировать эту таблицу так, чтобы можно было быстро запрашивать данные.   -  person iCoffee    schedule 08.02.2013
comment
Это наводит на мысль сделать нормализацию: для каждого такого текстового столбца я создам дополнительную таблицу со списком всех различных значений, которые могут появиться в этом столбце, затем я создам (tinyint) первичный ключ.. . Кажется, вы думаете, что нормализация и использование суррогатных ключей — это одно и то же. Они не. Нормализация означает, что вы эффективно уменьшаете количество столбцов в исходной таблице, проецируя новые таблицы на основе функциональных, многозначных зависимостей и зависимостей соединения.   -  person Mike Sherrill 'Cat Recall'    schedule 09.02.2013
comment
в таблице нет индексов!!!!!!!!! PS Индексация включает в себя СУБД, создающую и организующую идентификаторы для значений.   -  person philipxy    schedule 08.07.2017


Ответы (4)


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

Однако это также, вероятно, улучшит скорость запросов; в настоящее время наличие одной строки, содержащей 300 текстовых столбцов, является огромным и почти наверняка превышает 8060. байт для хранения страницы данных строки... и вместо этого хранится в ROW_OVERFLOW_DATA или LOB_DATA единицах размещения.

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

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

person Michael Fredrickson    schedule 07.02.2013
comment
Михаил, спасибо за ваши комментарии! Эти 8 КБ и есть то, что происходит на самом деле. - person iCoffee; 08.02.2013

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

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

Кроме того, SQL Server перенесет столбцы varchar на дополнительные страницы. Не проливает другие виды. У вас есть только 300 столбцов, но в конечном итоге ваши данные записи могут приблизиться к пределу 8 КБ для данных на одной странице.

И, если вы решите продолжить, я бы посоветовал вам искать «темы» в колонках. Могут быть группы столбцов, которые можно сгруппировать вместе. . . подробный код остановки и категория остановки, краткое название компании и полное название компании. Вы идете по пути моделирования данных (хорошо). Но будьте осторожны при выполнении действий на очень низком уровне (управление 100 справочными таблицами) по сравнению с определением разумного набора сущностей и отношений.

person Gordon Linoff    schedule 07.02.2013
comment
Гордон, большое спасибо за высказывание вашего мнения! Пункт с группировкой столбцов по их значению действительно очень полезен. - person iCoffee; 08.02.2013

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

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

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

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

person David Burton    schedule 07.02.2013
comment
Дэвид, ваше замечание о более внимательном рассмотрении процесса кэширования очень многообещающе. Спасибо за то, что поделились своими мыслями! - person iCoffee; 08.02.2013

  1. Построить в уме и на бумаге нормализованную структуру базы данных
  2. Построить базу данных (с индексами)
  3. Разрушьте этот монолит. Все будет выглядеть не так уж плохо. Я бы предположил, что МНОГО (Я ОЗНАЧАЮ МНОГО) данных повторяется
  4. Создайте операторы вставки SQL для вставки данных в базу данных.
  5. Идите к тем, кто создал этот кошмар, с дробовиком. Развлекайся.
person Ed Heal    schedule 07.02.2013