Я ищу, чтобы хранить отсортированный список в базе данных. Я хочу эффективно выполнить следующие операции.
- Вставить (x) - Вставить запись x в таблицу
- Удалить (x) - удалить запись x из таблицы
- Before (x, n) - вернуть 'n' записей, предшествующих записи x в отсортированном списке.
- После (x, n) - вернуть 'n' записей, следующих за записью x в отсортированном списке.
- First (n) - вернуть первые 'n' записей из отсортированного списка.
- Last (n) - вернуть последние 'n' записи из отсортированного списка.
- Сравнение (x, y) - Учитывая две записи x и y из таблицы, найдите, если x> y.
Простой метод, который я мог бы придумать, - это сохранить в таблице какой-то атрибут «ранг» и выполнить запрос путем сортировки по этому атрибуту. Но в этом методе вставка / изменение записи с рангом становится дорогостоящей операцией. Есть ли лучший метод?
В частности, я хочу реализовать таблицу с помощью Amazon SimpleDB. Но общий ответ для реляционной базы данных также должен быть полезным.
Обновление профиля нагрузки:
Поскольку я планирую это для веб-приложения, это зависит от количества пользователей, которые используют приложение.
Если есть 100 000 активных пользователей (супер оптимизм: P), то моя очень приблизительная оценка в день будет
500 тыс. Выбирает, 100 тыс. Вставляет и удаляет, 500 тыс. Обновлений
Я ожидаю, что таблица вырастет в общей сложности до 500 тысяч.
Я хочу оптимизировать обновления, операции вставки и сравнения. Ранг предметов будет постоянно меняться, и мне нужно постоянно обновлять таблицу.
источник
Ответы:
Если ранг не является полностью произвольным, а может быть получен из какого-либо другого свойства (например, имени, счета игрока и т. Д.), Внимательно посмотрите на ответ Джоэла .
Если это произвольное свойство данных, то , что должно быть сохранено в качестве столбца в таблице рекордов. Предполагая, что Amazon SimpleDB похожа на типичную СУБД, вы можете затем проиндексировать этот столбец и быстро удовлетворить все вышеперечисленные запросы с помощью соответствующей стратегии индексации. Это нормально для РСУБД.
Учитывая, что вы ожидаете высокую активность вставки и обновления, а также относительно высокую активность чтения, я рекомендую сделать следующее:
INCLUDE
-ing ранга, или просто для записи, если вы кластеризовались по рангу) будет удовлетворять запросу 7.FILLFACTOR
в SQL Server). Это особенно важно, если вы группируете по рангу.Если вы ожидаете 100K + чтения для таблицы размером 100K +, я не рекомендую использовать метод связанного списка. Это не будет хорошо масштабироваться до этих размеров.
источник
FILLFACTOR
то увидите, что в основном это означает создание дополнительного пространства для записей в индексе, точно так же, как разрывы рангов, которые я описал, создают пространство для изменений рангов и вставок.Я обычно использую метод ранга, который вы описываете. Вместо того, чтобы возиться с обновлением строк, когда необходимо переупорядочить элементы, мне часто удавалось удалить все записи в списке и заново вставить новые элементы в правильном порядке. Этот метод явно оптимизирован для поиска.
Альтернативный подход заключается в том, чтобы смоделировать записи в виде связанного списка, используя столбец рефлексивного внешнего ключа «предшественника» в таблице:
Вы можете легко получить список и добавлять и удалять элементы с небольшими накладными расходами, но вывести записи в правильном порядке будет непросто. Возможно, есть умный способ сделать это в одном запросе, возможно, с множеством объединенных таблиц.
Я часто использую этот последний подход, когда моделирую древовидные отношения (категории, папки, наборы и подмножества). У меня обычно была какая-то рекурсивная функция для восстановления полного дерева в моем приложении.
источник
Я думаю, что нужно сохранить свойство или свойства, которые используются для вычисления ранга, а затем построить индекс по ним. Вместо того, чтобы заставлять базу данных физически хранить данные в ранжированном порядке или использовать связанный вручную список, почему бы не позволить ядру базы данных сделать то, для чего он предназначен?
источник
Это ограничения не-СУБД, как simpleDB. Необходимые функции не могут быть реализованы на стороне БД в simpleDB, они должны быть реализованы на стороне программирования / приложения.
Для подобных СУБД требуемые
SQL server
функции являются элементарными по отношению к кластерному индексу.Before (x, n) - вернуть 'n' записей, предшествующих записи x в отсортированном списке. > Выберите top n результатов, где x меньше значения и упорядочите по выражению.
После (x, n) - вернуть 'n' записей, следующих за записью x в отсортированном списке. > Выберите top n результатов, где x больше значения и упорядочите по выражению.
First (n) - вернуть первые 'n' записей из отсортированного списка. > Выберите лучшие n результатов.
Last (n) - вернуть последние 'n' записи из отсортированного списка. > Выберите лучшие n результатов после заказа по дес.
источник
Вот что я использовал для ранжирования моей таблицы Postgres после каждой вставки:
Для моего варианта использования производительность не имеет значения, но важна уверенность в том, что она никогда не сломается или не будет действовать странным образом.
источник