如果您尝试在数据库模式中创建域对象,并且在代码中所述域对象具有哈希表/列表成员,如下所示:

public class SpaceQuadrant : PersistentObject
{

    public SpaceQuadrant()
    {
    }

    public virtual Dictionary<SpaceCoordinate, SpaceObject> Space
    {
        get;
        set;
    }
}

字典只是一个将对象键映射到值键的哈希表/列表,我想出了多种方法来做到这一点,创建各种连接表或加载技术,但它们在获得 O(1) 方面都有点糟糕您在哈希表中获得的访问时间。

您将如何在数据库模式中表示 SpaceQuadrant、SpaceCooperative 和空间对象?一个简单的架构代码描述很好,即。

table SpaceQuadrant
{
    ID int not null primary key,
    EntryName varchar(255) not null,
    SpaceQuadrantJoinTableId int not null
                 foreign key references ...anothertable...
}

但任何想法都很好,感谢您的阅读!

更多信息:

感谢您的精彩回答,我只是浏览了一下,在回复之前我想花一些时间思考一下每个问题。

如果您认为有更好的方法来定义这些类,那么请务必给我举一个例子,任何您熟悉的语言都可以

有帮助吗?

解决方案

首先,对地理定位的数据专用的支持在许多数据库中存在 - 不同的算法都可以使用(B树的空间版本存在例如),以及用于接近支持,可能搜索会存在

既然你有不同的哈希表中的每个SpaceQuadrant,你需要像(来自美国洛特的帖子编辑):

table Space {
    SpaceCoordinate,
    Quadrant Foreign Key SpaceQuadrant(ID),
    SpaceObject -- whatever the object is (by ID)
    Primary Key(SpaceCoordinate, Quadrant)
}

这是一个(SpaceCoordinate, Quadrant) -> SpaceObjectId字典。

=====

现在,你的O(1)性能问题,有很多的原因,它的错误处理。

您可以在许多数据库的一个散列索引基于内存的表使用,因为有人告诉你。但是如果你需要持久化存储,你需要更新两个表(内存之一,并持续一个),而不是一个(如果对此没有内置支持)。要发现是否是值得,你需要对实际数据的基准(与实际数据的大小)。

另外,迫使一个表到存储器可以具有影响更糟。

如果一些曾经被调换,你就死定了 - 如果你曾经使用B树(即正常的基于磁盘的指数),它的算法会最小化所需的I / O。否则,所有的DBMS将使用哈希表并且依靠交换,而不是B-树。你可以尝试预测是否会存放在内存,但...

此外,B-树不是O(1)但它们是O(log_512(N)),或类似的东西(我知道合拢为为O(log N),但承受我在此)。你需要(2 ^ 9)^ 4 = 2 ^ 36 = 64GiB为为4,如果你有这么多的数据你需要一个大铁服务器反正是适合在内存中。因此,它几乎为O(1),并不断的因素究竟是什么重要的。结果 听说过的低渐近复杂性,大常数因子算法,这将是比简单的人只是不切实际的数据量更快?

最后,我认为DB作家比我和你聪明。尤其是考虑到SQL的声明性特性,手工优化这种方式是不是要去买单。如果索引装入内存,我想他们可以选择建立和使用的磁盘索引的哈希表的版本,根据需要,如果它是值得的。调查您的文档了点。

但底线是,过早的优化是邪恶的,尤其是当它的这种(我们正在考虑我们自己怪异的优化,而不是标准的SQL优化),并与说明性语言。

其他提示

关系不哈希表;它们是一组

我不会组织使用的坐标作为密钥数据库。如果一个对象改变位置?相反,我可能把坐标的属性的对象。

另外,我假定有一个固定维数,例如三个。如果是这样,那么就可以一个对象的这些属性存储在固定列:

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)时间,但你为什么这样做,通过协调?

如果您使用的优化发现,是附近某一点的对象(玩家的飞船,例如),你也可以建设成用于填充此SpaceQuadrant每个对象的距离的计算从给定的点您的SQL查询和由距离对结果进行排序。

我不知道有足够的了解你的程序就可以知道这些建议是相关的。但他们至少让你想到的组织数据的方式不同?

在最简单的情况下,字典有一个键可以映射到表的主键 - 这样当您指定键的值时,您可以通过简单的查找立即找到匹配的数据。

在这种情况下,您需要一个 SpaceQuadrant 表,其中包含描述或表征空间象限的任何常规(单值)属性。SpaceQuadrant 表将有一个主键,可能是一个生成的 ID,也可能是一个自然值。然后,哈希表将由一个表组成,该表具有用于交叉引用 SpaceQuadrant 的主键值、位置(SpaceCoordinate)以及象限和坐标的属性。

现在,如果您有可扩展的 DBMS,则可以为 SpaceCooperative 定义用户定义的类型;如果做不到这一点,您可以使用三列 - 例如 x、y、z 或 r、theta、rho - 来表示位置(空间坐标)。

一般来说,我所描述的结构与 Bill Karwin 的结构非常相似;关键(双关语直到我重新阅读消息之后才打算)区别在于,在我的书中,如果您确定这是组织的最佳方式,则将位置作为从属表的主键的一部分是完全可以的它。您可能还有一个对象 ID 列作为备用候选键。或者,如果对象的存在独立于它们当时所处的空间象限(或者可以存在于多个位置 - 因为它们不是点,而是空间站或其他东西),那么您可能会将 SpaceObject 放在单独的表。什么是最好的取决于我们无法获得的信息。

您应该了解使用 SpaceCoordinate 作为主键一部分的限制:

  • 没有两个对象可以占据相同的位置(这在哈希表和 3D 空间中称为碰撞),
  • 如果位置发生变化,则必须更新关键数据,这比更新非关键数据更昂贵,
  • 邻近查找会很困难 - 精确查找很容易。

你内存中的字典也是如此;如果更改坐标,则必须从旧位置删除记录并将其放置在字典中的新位置(或者语言必须在幕后为您执行此操作)。

一个字典的表。哈希是什么样的使用索引的问题。最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
}

您的空间物体必须在他们所在的象限FK引用。

根据您的RDBMS,你也许能找到一个基于散列的索引,让你你希望的性能。例如MySQL中,使用堆存储引擎支持哈希索引。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top