Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jsf-2/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 针对单个大型表的多对多关系_Sql_Database Design_Database Schema_Database Normalization - Fatal编程技术网

Sql 针对单个大型表的多对多关系

Sql 针对单个大型表的多对多关系,sql,database-design,database-schema,database-normalization,Sql,Database Design,Database Schema,Database Normalization,我有一个由5000个单元组成的几何图,每个单元都是任意多边形。我的应用程序将需要保存许多这样的图表 我已确定需要使用数据库对此地图进行索引查询。加载所有地图数据对于快速响应简单查询来说效率太低 我已将单元格数据添加到数据库中。它的结构相当简单: CREATE TABLE map_cell ( map_id INT NOT NULL , cell_index INT NOT NULL , ... PRIMARY KEY (map_id, cell_index) ) 每个映射5000

我有一个由5000个单元组成的几何图,每个单元都是任意多边形。我的应用程序将需要保存许多这样的图表

我已确定需要使用数据库对此地图进行索引查询。加载所有地图数据对于快速响应简单查询来说效率太低

我已将单元格数据添加到数据库中。它的结构相当简单:

CREATE TABLE map_cell (
map_id INT  NOT NULL ,
cell_index INT  NOT NULL ,

...    
PRIMARY KEY (map_id, cell_index)
)
每个映射5000行是相当多的,但是查询应该在数百万行中保持高效,因为主连接索引可以聚集。如果它变得太笨拙,可以在map_id边界上进行分区。尽管每个映射都有大量的行,但这个表还是具有相当大的可伸缩性

问题在于存储描述哪些单元彼此相邻的数据。小区邻居关系是针对同一个表的多对多关系。每个地图上也有大量这样的关系。规范化表可能如下所示:

CREATE TABLE map_cell_neighbors (
id INT  NOT NULL AUTO INCREMENT ,
map_id INT  NOT NULL ,
cell_index INT  NOT NULL ,
neighbor_index INT ,
...
INDEX IX_neighbors (map_id, cell_index)
)
此表需要一个永远不会在联接中使用的代理项键。此外,此表还包含重复项:如果小区0是小区1的邻居,则小区1始终是小区0的邻居。我可以消除这些条目,但需要额外的索引空间:

CREATE TABLE map_cell_neighbors (
id INT  NOT NULL AUTO INCREMENT ,
map_id INT  NOT NULL ,
neighbor1 INT  NOT NULL ,
neighbor2 INT  NOT NULL ,
...
INDEX IX_neighbor1 (map_id, neighbor1),
INDEX IX_neighbor2 (map_id, neighbor2)
)
我不确定哪一个会被认为更规范化,因为选项1包含重复的条目,包括复制关系的任何属性,而选项2是一些非常奇怪的数据库设计,感觉不规范。这两种选择都不是很节省空间。对于10张地图,选项1使用了300000行,占用了1200万文件空间。选项2是150000行,占用了8M的文件空间。在这两个表上,索引占用的空间都比数据多,考虑到数据每行大约20个字节,但实际上磁盘上需要40-50个字节

第三个选项根本不会被规范化,但会非常节省空间和行。它包括在map_单元中放置一个VARBINARY字段,并在单元表本身中存储一个二进制压缩的邻居列表。这将需要每个单元24-36字节,而不是每个关系40-50字节。它还将减少总的行数,并且由于集群主键,对单元格表的查询将非常快。但是,对该数据执行连接是不可能的。任何递归查询都必须一步一步地完成。而且,这是一个非常丑陋的数据库设计

不幸的是,我需要我的应用程序能够很好地伸缩,并且只需要50个映射就不会遇到SQL瓶颈。除非我能想出其他办法,否则后一种办法可能是唯一真正有效的办法。在我将这样一个卑鄙的想法应用于代码之前,我想确保我清楚地看到了所有的选项。可能还有另一种设计模式我没有想到,或者我所预见的问题并不像它们看起来那么糟糕。不管是哪种方式,我都想在做这件事之前得到其他人的意见


针对该数据的最复杂查询将是路径查找和路径发现。这些将是递归查询,从特定单元格开始,经过几次迭代遍历相邻单元格,并收集/比较这些单元格的属性。我很确定我不能在SQL中完成所有这些,可能会有一些应用程序代码贯穿其中。我希望能够以中等规模执行类似这样的查询,并在可接受的时间内(大约一秒钟)获得结果,以便对用户做出响应。总体目标是防止大表大小导致重复查询或固定深度递归查询花费几秒钟或更长时间。

不确定您正在使用哪个数据库,但您似乎正在重新发明支持空间的数据库所支持的功能

例如,如果SQL Server是一个选项,则可以将多边形存储为几何体类型,使用内置的空间索引和符合OGC的方法,如STContains、stcrosss、STOverlaps和sttouch

SQL Server spatial indexes在将多边形分解为不同的b树层后,还使用细分来索引给定多边形在树索引的给定层上接触的相邻单元


还有其他支持空间类型的主流数据库,包括

您的主要目标是空间效率还是执行效率?您希望对这些数据进行什么样的查询?举个例子就好了,我的目标是将两者都保持在可接受的范围内。执行效率很重要,但我不想在仍然需要处理AJAX开销的情况下进行过度优化。如果我们不谈论千兆字节,那么空间效率并不是非常重要,但它是服务器空间。我主要关心的是防止大型表破坏SQL查询时间。最复杂的查询将是递归查询,从s开始
单个细胞向外分支,然后根据这些细胞的特性做出决定。这将通过SQL和应用程序代码的混合来完成。1在您的模式中,外键似乎丢失了2不需要枚举邻居,一个简单的单元到单元{neighbour1neibour2}连接表就足够了,有两个外键,显然3是图的无向性吗?我想这是4个循环永远是个问题;至少在SQL.1中,外键肯定会有帮助。2 map_cell_neights就是这样一个连接表,减去外键。基本上,索引应该是外键。我关心的是速度,当它快速到达数百万排时。3是的。这是一个Voronoi图,它已被放宽以规范化单元大小。4我不确定我是否能够避免将每次迭代作为一个单独的查询,并在应用程序代码中做出一些决策。我也许可以使用子查询来挖掘到一个固定的深度,但我很清楚SQL循环的问题。我更愿意在应用程序代码中做这样的事情。这绝对是我一直在寻找的东西。我不知道有这样的特征存在。我的应用程序运行在运行MySQL的Linux web服务器上。看起来MySQL也提供了这样的功能。问题:在WHERE子句中使用这些空间关系测试真的非常有效吗?我的查询是这样的:选择*FROM map_cell c1 LEFT JOIN map_cell c2 ON c1.map_id=c2.map_id并触摸esc1.geom,c2.geom以返回特定单元格的所有邻居。假设表中有100000多行和5000行符合c1.map_id=c2.map_id标准,它是否能够以最佳方式处理这样的查询?我熟悉SQL Server,但不熟悉MySQL,因此无法具体说明。抽象地说,使用支持空间的db引擎来执行该查询将是最优化的方法,而不是尝试执行大型非空间递归。更具体地说,通过更好地阐明您的需求来回答性能问题。这是一次性查询吗?一次只对一个单元格执行的是动态的吗?如果地图数据是静态的,您可以创建一个包含所有接触单元格的笛卡尔积的表,并填充一次或定期更新查询通常是递归的。我经常需要从一个或多个小区位置进行分支,并查找特定范围内的所有小区,就像查找视线范围或移动范围内的所有小区一样。地图图是固定的。一旦生成,单元属性可能会改变,但图表的结构永远不会改变。如果两个细胞是相邻的,它们将始终保持相邻状态。然而,笛卡尔乘积是每个映射15000个关系,我担心这会在某个时候压倒SQL。我的OP演示了这样一个表,以及它将以多快的速度增长。尽管如此,我还是建议您先使用几何体类型和函数。在集合中思考,或者在本例中,一组单元格可能被量化为一个边界框,并且可能可以消除递归。此外,虽然笛卡尔乘积表可能有数千行,但其目标是消除任何运行时计算,并且是一个简单的按单元格索引的查找……但只有在符合您的需求时才进行查找。