如果您尝试在数据库模式中创建域对象,并且在您的代码中,则表示域对象具有哈希表/列表成员,如下所示:
public class SpaceQuadrant : PersistentObject
{
public SpaceQuadrant()
{
}
public virtual Dictionary<SpaceCoordinate, SpaceObject> Space
{
get;
set;
}
}
字典只是一个哈希表/列表映射对象键值键,我已经提出了多种方法来创建它,创建各种连接表或加载技术,但它们在获取O方面都很糟糕(1)访问哈希表中的时间。
您如何在数据库模式中表示SpaceQuadrant,SpaceCoordinate和Space Object? 一个简单的架构代码描述会很好, 即
table SpaceQuadrant
{
ID int not null primary key,
EntryName varchar(255) not null,
SpaceQuadrantJoinTableId int not null
foreign key references ...anothertable...
}
但是任何想法都会很好,感谢阅读!
更多信息:
感谢你们给出了很好的答案,我只是撇去了他们,我想在回应之前花点时间思考一下。
如果您认为有更好的方法来定义这些课程,那么无论如何都要向我展示一个例子,您喜欢的任何语言都很酷
答案 0 :(得分:2)
关系不是哈希表;他们是一套。
我不会使用坐标作为关键字来组织数据库。如果对象改变位置怎么办?相反,我可能会将坐标视为对象的属性。
此外,我假设有固定数量的维度,例如,三个。如果是这样,那么您可以将对象的这些属性存储在固定列中:
CREATE TABLE SpaceQuadrant (
quadrant_id INT NOT NULL PRIMARY KEY,
quadrant_name VARCHAR(20)
-- other attributes
);
CREATE TABLE SpaceObject (
object_id INT NOT NULL PRIMARY KEY,
x NUMERIC(9,2) NOT NULL,
y NUMERIC(9,2) NOT NULL
z NUMERIC(9,2) NOT NULL,
object_name VARCHAR(20) NOT NULL,
-- other attributes
quadrant_id INT NOT NULL,
FOREIGN KEY (quadrant_id) REFERENCES SpaceQuadrant(quadrant_id)
);
在面向对象的类中,不清楚为什么对象在字典中。你提到在O(1)时间访问它们,但为什么你通过坐标来做到这一点?
如果您正在使用它来优化查找某个点附近的对象(例如,玩家的太空船),您还可以构建到您的SQL查询中,该查询会填充此SpaceQuadrant,计算每个对象距该给定点的距离,并按距离对结果进行排序。
我对您的计划了解不足以了解这些建议是否相关。但他们至少会让你想到组织数据的不同方式吗?
答案 1 :(得分:2)
在最简单的情况下,字典有一个键映射到表的主键 - 这样当您指定键的值时,您可以通过简单的查找立即找到匹配的数据。
在这种情况下,您需要一个表SpaceQuadrant,其中包含描述或表征空间象限的任何通用(单值)属性。 SpaceQuadrant表将具有主键,可能是生成的ID,可能是自然值。然后,散列表将包含一个表,其中主键值用于交叉引用SpaceQuadrant,其中包含位置(SpaceCoordinate)以及象限和坐标的属性。
现在,如果您有可扩展的DBMS,则可以为SpaceCoordinate定义用户定义的类型;如果不这样做,你可以使用三个列 - 例如x,y,z或r,theta,rho--来表示位置(SpaceCoordinate)。
总的来说,我所描述的结构与Bill Karwin非常相似;关键(在我重读信息之前没有意图)不同之处在于,如果您确定这是最好的组织方式,那么在我的书中完全可以将该位置作为子坐标表主键的一部分。它。您可能还有一个对象ID列,它是备用候选键。或者,如果对象具有独立于空间象限的存在,它们恰好位于当前(或者可以存在于多个位置 - 因为它们不是点而是空间站或某些东西),那么您可能拥有空间对象单独的表。什么是最好的取决于我们没有的信息。
您应该了解使用SpaceCoordinate作为主键的一部分的限制:
你的字典在记忆中也是如此;如果更改坐标,则必须从旧位置删除记录并将其放在字典中的新位置(或者语言必须在幕后为您执行此操作)。
答案 2 :(得分:2)
字典是表。哈希是一个使用何种索引的问题。大多数RDBMS都假设表格大且密集,使得散列索引不合适。
table SpaceQuadrant {
ID Primary Key,
-- whatever other attributes are relevant
}
table Space {
SpaceCoordinate Primary Key,
Quadrant Foreign Key SpaceQuadrant(ID),
SpaceObject -- whatever the object is
}
您的Space对象具有对它们所在的象限的FK引用。
根据您的RDBMS,您可能能够找到一个基于哈希的索引,可以获得您希望的性能。例如MySQL,使用HEAP存储引擎支持HASH索引。
答案 3 :(得分:1)
首先,许多数据库中都存在对地理位置数据的专用支持 - 可以使用不同的算法(例如,存在B树的空间版本),并且可能存在对邻近搜索的支持。
由于每个SpaceQuadrant都有一个不同的哈希表,你需要类似的东西(从S.Lott的帖子编辑):
table Space {
SpaceCoordinate,
Quadrant Foreign Key SpaceQuadrant(ID),
SpaceObject -- whatever the object is (by ID)
Primary Key(SpaceCoordinate, Quadrant)
}
这是(SpaceCoordinate, Quadrant) -> SpaceObjectId
词典。
=====
现在,关于你的O(1)性能问题,有很多原因导致它被错误地解决。
正如有人告诉你的那样,你可以在许多DB中使用基于内存的表的哈希索引。但是如果你需要持久存储,你需要更新两个表(内存一个和持久存储)而不是一个(如果没有内置的支持)。要发现这是否值得,您需要对实际数据(实际数据大小)进行基准测试。
此外,强制将表放入内存可能会产生更糟糕的影响。
如果某些东西被交换了,那么你已经死了 - 如果你使用过B-Tree(即普通的基于磁盘的索引),它的算法会最小化所需的I / O.否则,所有DBMS都将使用哈希表并依赖于交换,而不是B-Trees。你可以试着预测你是否适合记忆,但是......
此外,B-Trees不是O(1)但是它们是O(log_512(N)),或类似的东西(我知道崩溃到O(log N),但请耐心等待)。你需要(2 ^ 9)^ 4 = 2 ^ 36 = 64GiB为4,如果你有这么多的数据,你需要一个大的铁服务器,以适应内存。所以,它几乎是O(1),而常数因素实际上是重要的 曾经听说过低渐近复杂度,大常数因子算法,这些算法比不简单的数据大小更简单吗?
最后,我认为数据库作者比我和你聪明。特别是考虑到SQL的声明性,以这种方式手动优化它不会付出代价。如果索引适合内存,我猜他们可以根据需要选择构建和使用磁盘索引的哈希表版本,如果值得的话。调查你的文档。
但最重要的是,过早的优化是邪恶的,特别是当它属于这种类型时(我们自己在考虑奇怪的优化,而不是标准的SQL优化),并且使用声明性语言。