Вопрос

Я использую MS SQL Server 2005.

Какая схема лучше всего подходит для Wiki-подобной системы?где пользователи редактируют/пересматривают материалы, а система отслеживает эти материалы.

Допустим, мы создаем простую систему на основе Wiki.Будет отслеживать каждую редакцию, а также просмотры и последние действия по каждой ревизии.На других экранах система отобразит «Последние публикации» и «Самые просматриваемые», а также поиск по названию.

Моя текущая схема (и я знаю, что она плоха) использует одну таблицу.Когда мне нужно просмотреть «Последние отправленные материалы», я сортирую их по «LatestActivity», группирую по «DocumentTitle», а затем беру первые N записей.Я предполагаю, что большая группировка (особенно группировка по nvarchar) — это плохая новость.Для перечисления наиболее просматриваемых я делаю то же самое:сортировать по представлениям, группировать по имени, брать первые N записей.Большую часть времени я также буду использовать «WHERE DocumentName LIKE '%QUERY-HERE%'».

Моя текущая схема — «Версия 1», см. ниже:альтернативный текст http://www.anaimi.com/junk/schemaquestion.png

Я предполагаю, что это неприемлемо.Поэтому я пытаюсь придумать другой/более эффективный дизайн.Как вам версия 2?Во второй версии я получаю преимущество группировки по WikiHeadId, который является числом - я предполагаю, что группировка по числу лучше, чем nvarchar.

Или крайний случай — версия 3, в которой я не буду группировать, но она имеет ряд недостатков, таких как дублирование значений, сохранение этих значений в коде и т. д.

Или существует ли лучшая/известная схема для таких систем?

Спасибо.

(перенесено из ServerFault - я думаю, что это скорее вопрос разработки, чем вопрос ИТ)

Это было полезно?

Решение

Во-первых (и из любопытства), как текущая схема указывает на текущую версию?У вас есть несколько записей «Вики-документ» с одним и тем же названием документа?

Мне также неясно, зачем вам нужна «LastActivity» на уровне версии.Я не понимаю, как «LastActivity» соответствует концепции «Версии» - в большинство вики, «версии» доступны для однократной записи:если вы изменяете версию, вы создаете новый версию, поэтому концепция значения последнего обновленного типа в версии бессмысленна — на самом деле это просто «дата создания».

На самом деле «естественная» схема вашего дизайна — №2.Лично я немного поклонник старой аксиомы БД: «нормализуй, пока не станет больно, затем денормализуй, пока не заработает».№2 — более чистый и приятный дизайн (простой, без дублирования), и если у вас нет срочной причины денормализовать его до версии 3, я бы не стал заморачиваться.

В конечном итоге дело сводится к следующему:Вы беспокоитесь о «более производительном» дизайне, потому что заметили проблемы с производительностью или потому, что гипотетически мощь есть немного?Нет никакой реальной причины, по которой №2 не должен работать хорошо.Группировка не обязательно является плохой новостью для SQL Server — на самом деле, если для запроса имеется подходящий индекс покрытия, он может работать очень хорошо, поскольку можно просто перейти к определенному уровню индекса, чтобы найти сгруппированные значения, а затем использовать остальные столбцы индекса будут использоваться для MIN/MAX/что угодно.Группировка по NVARCHAR не так уж и плоха — если она не является проблемой, не беспокойтесь об этом, хотя (недвоичные) параметры сортировки могут немного усложнить задачу — но в версии 2, где вам нужно GROUP BY вы можете сделать это по WikiHeadId, верно?

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

SELECT TOP ...
FROM WikiHead
INNER JOIN 
  (SELECT WikiHeadId, MAX(WikiBodyVersion) /* or LastUpdated? */ AS Latest 
   FROM WikiBody GROUP BY WikiHeadId) AS LatestVersions
INNER JOIN WikiBody ON 
  (Latest.WikiHeadId = WikiBody.WikiHeadId)
  AND (WikiBody.WikiBodyVersion = LatestVersions.Latest)
ORDER BY 
  Views DESC

или альтернативно

...
INNER JOIN WikiBody ON 
  (WikiHead.WikiHeadId = WikiBody.WikiHeadId)
  AND (WikiBody.WikiBodyVersion = 
    (SELECT MAX(WikiBodyVersion) FROM WikiBody WHERE WikiBody.WikiHeadId = WikiHead.WikiHeadId)
...

и то, и другое отвратительно.Если WikiHead сохраняет указатель на текущую версию, это просто

...    
INNER JOIN WikiBody ON 
  (WikiHead.WikiHeadId = WikiBody.WikiHeadId)
  AND (WikiHead.Latest = WikiBody.WikiBodyVersion)
...

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

Другие советы

Проверять этот вне.

Это схема базы данных для медиавики, на чем основана википедия.

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

Из этого страница.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top