Фон: Профессиональный инструмент разработчика. SQL/DB любитель.Удаление дублирования строк в базе данных SQL Server 2008
Установка: .NET 3.5 WinForms приложения говорить с MS SQL Server 2008.
Сценарий: я заполнение базы данных с информацией, извлеченной из большого количества файлов. Это составляет около 60 М записей, каждый из которых имеет связанное с ним сообщение произвольного размера. Мой первоначальный план состоял из nvarchar (max) поля в записи для хранения сообщений, однако после выполнения тестового прогона в подмножестве данных это сделало базу данных слишком большой (экстраполируется на недопустимый 113 ГБ). Запустив несколько запросов в этом первоначальном наборе тестовых данных (база данных 1,3 ГБ), я обнаружил, что произошло значительное дублирование сообщений, и мы могли бы использовать это, чтобы уменьшить данные сообщений примерно на одну шестую. Я пробовал и думал о нескольких подходах к достижению этого, но ни один из них не является удовлетворительным. Я обыскал в течение нескольких дней, но либо: а) не кажется, что это хороший ответ (маловероятно), или б) я не знаю, как выразить то, что мне нужно достаточно хорошо (скорее).
Подходы, рассмотренные/пробовали:
- Массовые вставки сообщений в записи с NVARCHAR (макс) поле. - обнаружено, что у них слишком много избыточности.
- Придерживайтесь этого столбца сообщения, но найдите способ заставить базу данных «сжать» сообщения. - не знаю, как это сделать.
- Добавить таблицу сообщений для уникальных сообщений с ключом на идентификаторе, в котором находится основная запись (ы). - в то время как работа в принципе, реализация уникальности оказывается болезненной и страдает от замедления по мере добавления большего количества сообщений.
- Выполните дублирование на клиенте. - требует, чтобы все сообщения были отправлены клиенту для каждого сеанса населения. Это не масштабируется, так как им нужно будет вписываться в память.
- Добавьте в таблицу сообщений дополнительный (индексированный) хэш-столбец и отправьте сообщения с соответствующим (локально сгенерированным) хэш-значением. Найдите это, чтобы сузить сообщения, которые на самом деле нуждаются в тестировании. - сложный, должен быть лучший способ.
Этот третий подход представляет собой создание таблицы словаря строк. После нескольких итераций по этой идее я закончил с следующее:
- База данных содержит таблицу сообщений, которая сопоставляет (автоматический назначенный) INT ID первичный ключ к NVARCHAR (макс) сообщение ,
- Клиент отправляет сообщения и отправляет несколько записей для вставки в хранимую процедуру.
хранимая процедура перебирает партии входящих записей, и для каждого сообщения:
я. Таблица словаря сообщений проверяется (SELECT) для существующего экземпляра сообщения.
ii. Если найдено, запомните идентификатор существующего сообщения.
iii. Если не найден, вставьте новую запись сообщения, запомните идентификатор новой записи (OUTPUT).
Идентификаторы для всех сообщений (старые и новые) возвращаются в качестве результата результата, установленного в процедуре.
- Клиент создает основные записи таблицы с записями (int внешних ключей) для сообщений, заполненных идентификаторами, возвращаемыми процедурой.
Вопросы:
- Поиск существующих сообщений становится все медленнее и медленнее, так как количество сообщений растет, становится ограничивающим фактором.
- Я попытался проиндексировать (UNIQUE) столбец сообщений, но вы не можете индексировать nvarchar (max) column.
- Я просмотрел возможности полнотекстового поиска MS SQL Server 2008, но для меня это кажется излишним.
- Я думал о попытке MERGE в пакетах сообщений, но я не вижу способа легко получить соответствующий список идентификаторов (старый и новый, в правильном порядке), чтобы вернуть клиенту ,
Мне кажется, что я пытаюсь добиться какой-то нормализации своих данных, но из того, что я понимаю в дизайне базы данных, это больше похоже на «нормализацию строк», чем правильная нормализация, которая имеет значение «столбец» нормализация. Я удивлен, что это не то, что нужно повсюду, с соответствующей поддержкой уже.
Итак, мой вопрос: Каков правильный подход?
Любая помощь очень ценится.
Сэм
Каковы ваши целевые показатели производительности и ресурсов? Как быстро вам нужно вставлять записи? Почему 113 ГБ слишком много данных? Вам действительно нужно использовать nvarchar (max)? Не могли бы вы использовать меньший столбец и помещать несоответствующие данные в специальную таблицу (которая закончилась бы меньшим количеством строк)? –
Да, я понимаю, что я немного расплывчато о цели. Население не * действительно * проблема, так как это одноразовая (плюс текущие небольшие обновления). Тем не менее, тестовый прогон занял около часа, поэтому, предполагая линейное масштабирование, мы смотрим около 100 часов. Я бы хотел, чтобы это было быстрее, так как это заставляло репопуляцию при разработке системы довольно дорого. Некоторые из сообщений превышают 4000-символьный предел экспансивного размера varchar, поэтому теоретически мне нужно «max». Отдельная таблица для несоответствующих сообщений - интересная идея, хотя ... – Gaspode
В качестве примечания стороны, max 'varchar' составляет 8000; Максимальный размер nvarchar составляет 4000. –