0

我正在寻找为用户创建一个表格并跟踪他们的目标。目标本身将在 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 是否有可行的替代方案?一般方法有缺陷吗?我对想法持开放态度!

谢谢!

*编辑:如果可能的话,我希望能够仅通过数据修改而不是表修改来添加更多目标。但同样,我对想法持开放态度!

4

2 回答 2

1

执行此操作的正统方法根本不涉及位集。您有一个用户表、一个目标表和一个连接表,指示用户具有哪些目标。就像是:

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 端使用 Set,而不是 bitset。这很好地映射到连接表上。你考虑过这样做吗?

如果您担心内存消耗,一个集合将使用用户实际拥有的每个目标大约一个指针;bitset 将根据可能的目标使用一点。大多数 JVM 都有 32 位指针(只有旧的或大堆的 64 位 JVM 有 64 位指针),因此如果每个用户的平均可能目标少于 1/32,则该集合将使用更少的内存。有一些 groovy 数据结构将能够比其中任何一个结构更紧凑地存储这些信息,但让我们把它留给另一个问题。

于 2011-02-20T00:36:36.900 回答
1

[戴上假胡子]

将位集存储为BLOB。首先简单地对其进行序列化,然后如果您想要更高的空间效率,请尝试通过 DeflaterOutputStream 将结果推送到数据库。为了获得更好的空间和时间效率,请尝试FastBit中使用的位图压缩方法,它将位集分解为 31 位块,然后运行长度编码全零块,将文字和运行块打包成 32 位字带有鉴别器位。

如果您知道您只会在从数据库中获取它的 ResultSet 仍然打开时查看目标 bitset,请编写一个包装 Blob 接口并在 getBytes 之上实现 get 的新 bitset 类。这避免了必须将整个 BLOB 读入内存来检查一些特定位,并且如果您确实想查看所有值,至少可以避免必须为位集分配单独的缓冲区。请注意,使用压缩位集进行这项工作将需要大量的独创性。

请注意,这种方法没有参考完整性,也没有查询用户-目标关系的能力,未来对数据的不同用途的灵活性很小,这正是Don Knuth 警告你的那种事情。

于 2011-02-21T20:18:59.897 回答