Дерби - Как обрабатывать дополнения к целевым полям - PullRequest
0 голосов
/ 20 февраля 2011

Я хочу создать таблицу для пользователей и отслеживать их цели. Сами цели будут порядка 100, если не 1000, и будут храниться в их собственной таблице, но он не будет знать, кто их выполнил - он будет определять только те задачи, которые доступны.

Objective:
ID  |  Name   |  Notes  |
----+---------+---------+
    |         |         |

Теперь в среде Java у пользователей будет java.util.BitSet для этих целей. Так что я могу пойти

/* in class User */
boolean hasCompletedObjective(int objectiveNum) {
    if(objectiveNum < 0 || objectivenum > objectives.length())
        throw new IllegalArgumentException("Objective " + objectiveNum + " is invalid. Use a constant from class Objective.");
    return objectives.get(objectivenum);
}

Внутренне я знаю, что BitSet использует long [] для хранения. Как лучше всего представить это в моей базе данных Derby? Я бы предпочел сохранить его в столбцах таблицы AppUser, если это вообще возможно, потому что они действительно являются элементами пользователя.

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

SELECT *
FROM AppUser
WHERE AppUser.ObjectiveXYZ

Какие у меня есть варианты, как для хранения, так и для маршалинга в BitSet? Существуют ли жизнеспособные альтернативы java.util.BitSet? Есть ли недостаток в общем подходе? Я открыт для идей!

Спасибо!

* РЕДАКТИРОВАТЬ: Если это вообще возможно, мне бы хотелось добавить больше целей только с модификацией данных, а не с таблицей. Но опять же, я открыт для идей!

Ответы [ 2 ]

1 голос
/ 21 февраля 2011

[накладывает искусственные усы]

Сохраняет набор битов как BLOB .Начните с простого сериализации, затем, если вы хотите повысить эффективность использования пространства, попробуйте протолкнуть результаты через DeflaterOutputStream по пути к базе данных.Для повышения эффективности использования пространства и времени попробуйте использовать метод сжатия растровых изображений, используемый в FastBit , который разбивает битовый набор на 31-битные порции, затем кодирует по длине прогона все нулевые порции, упаковывает литералы и порции исполненияв 32-битные слова вместе с битом дискриминатора.

Если вы знаете, что вы будете смотреть только на целевой набор битов, пока ResultSet, который вывел его из базы данных, еще открыт, напишите новый класс наборов битов, который переноситИнтерфейс BLOB-объектов и их инструменты входят в число getBytes.Это избавляет от необходимости считывать весь большой двоичный объект в память, чтобы проверить несколько конкретных битов, и, по крайней мере, избавляет от необходимости выделять отдельный буфер для набора битов, если вы хотите просмотреть все значения.Обратите внимание, что выполнение этой работы со сжатым набором битов потребует значительной изобретательности.

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

1 голос
/ 20 февраля 2011

Ортодоксальный способ сделать это вообще не включает в себя наборы битов. У вас есть таблица для пользователей, таблица для целей и таблица соединений, указывающая, какие цели имеет пользователь. Что-то вроде:

create table users (
    id integer primary key,
    name varchar(100) not null
);

create table objectives (
    id integer primary key,
    name varchar(100) not null
);

create table user_objective (
    user_id integer not null references users,
    objective_id integer not null references objectives,
    primary key (user_id, objective_id)
);

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

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

Ортодоксальный подход также заключался бы в использовании набора на стороне Java, а не набора битов. Это очень хорошо отображается на столе соединения. Рассматривали ли вы сделать это таким образом?

Если вы беспокоитесь о потреблении памяти, набор будет использовать около одного указателя на цель, которую фактически имеет пользователь; битовый набор будет использовать немного для каждой возможной цели. Большинство JVM имеют 32-разрядные указатели (только старые или 64-разрядные JVM с огромной кучей имеют 64-разрядные указатели), поэтому, если у каждого пользователя в среднем меньше 1/32 возможных целей, набор будет использовать меньше памяти. Есть некоторые отличные структуры данных, которые смогут хранить эту информацию более компактно, чем любая из этих структур, но давайте оставим это другому вопросу.

...