SQL - Как пометить данные? - PullRequest
0 голосов
/ 15 мая 2011

Мне нужно хранить короткие теги (A01, B34 и т. Д.) В таблице SQL и убедиться, что они проиндексированы.Создание столбца INT для каждой буквы в алфавите невозможно, поскольку записи могут иметь несколько тегов «А», например.

Сначала я сохранил их в виде длинной строки, разделенной пробелами (например, «A01 B34»).«).Но для этого требуется запрос LIKE%, который выполняет полное сканирование и игнорирует все индексы.Поэтому я ищу альтернативы.

Теперь я использую SQLite FTS (текстовый поиск) для поиска этих тегов, но для этого требуется специальная таблица для хранения тегов, выборки результатов с помощью запросов JOIN и всех других вещей, которые я предпочел былюблю избегать.

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

Является ли мой текущий подход (делать фтс на тегах) самый быстрый?Или лучше использовать базу данных NoSQL для такого рода данных?

Ответы [ 4 ]

1 голос
/ 15 мая 2011

Я поделюсь своим опытом, как я это сделал, на моем предыдущем стартап-сайте сообщества Pageflakes. На Pageflakes пользовательский контент помечается. Вы можете увидеть пример здесь:

http://www.pageflakes.com/Community/Content/Flakes.aspx?moduleKey=4796

Каждый виджет подкачки имеет коллекцию тегов. Когда кто-то ищет, мы присваиваем тегам самый высокий приоритет, затем название, затем описание элемента.

Предположим, у вас есть таблица контента, подобная этой:

Content (id, title, description)

Прежде всего, вам нужно создать таблицу для всех уникальных тегов.

Tag (id, name (unique), countOfItems)

Затем вам нужно сопоставить тег со строками содержимого.

TagContentMap (tagid, contentid)

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

Кроме того, вставка всегда значительно ниже, чем выбор. Скорее всего, у вас будет 99% прочитанного, 1% записанного.

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

Теперь самый важный момент - как получить лучший результат поиска. В таблице содержимого у нас есть поле varchar с именем «SearchData». Это поле сначала заполняется именами тегов, затем заголовком и описанием. Таким образом,

SearchData = tag names comma delimited + newline + title + newline + description.

Затем вы используете полнотекстовое индексирование SQL Server для индексации только столбца SearchData, а не любого другого поля в таблице содержимого.

Это у вас работает?

1 голос
/ 15 мая 2011

Вы не даете нам много подробностей, но ваш дизайн кажется неправильным. Это не в третьей нормальной форме.

0 голосов
/ 15 мая 2011

Как отмечали другие пользователи, данные не очень хорошо нормализованы.Я предполагаю, что это преднамеренно, и есть некоторые очень большие (требование размера 100 ГБ или ТБ или огромное пропускная способность, о которой вы не упомянули).Но прежде чем вы начнете идти по любому пути, вы должны точно понять, каковы ваши требования: как часто вы пишете по сравнению с чтением, каковы требования к задержке при записи и чтении, и вы должны включить поддержку индексов в свои вычисления.

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

Если вы записываете в таблицу, например: данные таблицы (идентификатор двоичного (6), ..., отметка времени datetime, теги varchar (256))

и иметь вторичную таблицу: поиск по таблице (тег char (3), двоичный файл dataId (6))

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

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

0 голосов
/ 15 мая 2011

@ Джошуа, пожалуйста, смотри на термин "нормализация".В настоящее время ваши данные денормализованы.Денормализация возможная вещь.но после нормализации и как-то вроде взлома.В настоящее время ваш дизайн кажется неправильным.

Например, вы должны иметь одну таблицу из 3 таблиц:

some_records (id, column1, ..., columnN)
tags (id, title)
some_records_tags (some_record_id, tag_id)

Это классический шаблон проектирования в СУБД.И NoSQL здесь не нужен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...