如何以索引的方式高效地存储所有OpenStreetMap数据



注意:虽然我的目标是Windows Phone 7,但除了大小限制之外,它没有引入任何内容。

在尝试为Windows Phone 7编写GPS/Routing/Map应用程序时,我正尝试为此使用OpenStreetMap,我想将我的数据存储在Windows Phone 7上的SQL Server Compact Edition数据库中。这给我带来了很多麻烦,所以我不知道什么是正确的方法…

以下是我的进展:

  1. 我已经下载了Belgium.osm.pbf,它包含了PBF格式的所有比利时OSM数据。

    请注意,比利时并没有那么大,它是我居住的国家,所以这似乎是一个良好的开端。

    如果我的数据库接近PBF文件的大小,那就太好了,因为它只有80 MB。。。

  2. 使用MarcGravell的protobuf-net,我现在已经编写了一个解析器,它为我提供了所有的OSM数据。

  3. 在第一次尝试时,我试图将其全部加载到内存中,但这对我的Windows Phone 7来说似乎太大了,因为它导致大小>512 MB。当时的想法是,我需要一个数据库来存储这些信息,所以将其存储在SQL Server Compact Edition sdf文件中似乎是合乎逻辑的。

  4. 因此,我在LINQ to SQL中创建了以下DataContext和表:

    public class RoutingContext : DataContext
    {
        public RoutingContext()
    #if WINDOWS_PHONE
            : base("Data Source = 'isostore:/RoutingDB.sdf'; Max Database Size = 1024; Max Buffer Size = 65536")
    #else
            : base("Data Source = './RoutingDB.sdf'; Max Database Size = 1024; Max Buffer Size = 65536")
    #endif
        {
        }
        public Table<Node> Nodes;
        public Table<Road> Roads;
        public Table<RoadNode> RoadNodes;
        public Table<NodeProperty> NodeProperties;
        public Table<RoadProperty> RoadProperties;
        public Table<StringData> Strings;
    }
    [Table]
    public class Node
    {
        [Column(IsPrimaryKey = true)]
        public int Id { get; set; }
        [Column()]
        public int Lon { get; set; }
        [Column()]
        public int Lat { get; set; }
    }
    [Table]
    public class NodeProperty
    {
        [Column()]
        public int NodeId { get; set; }
        [Column(DbType = "NVarChar(255) NOT NULL")]
        public int Key { get; set; }
        [Column(DbType = "NVarChar(255) NOT NULL")]
        public int Value { get; set; }
    }
    [Table]
    public class RoadProperty
    {
        [Column()]
        public int RoadId { get; set; }
        [Column(DbType = "NVarChar(255) NOT NULL")]
        public int Key { get; set; }
        [Column(DbType = "NVarChar(255) NOT NULL")]
        public int Value { get; set; }
    }
    [Table]
    public class Road
    {
        [Column(IsPrimaryKey = true)]
        public int Id { get; set; }
    }
    [Table]
    public class RoadNode
    {
        [Column()]
        public int RoadId { get; set; }
        [Column()]
        public int NodeId { get; set; }
    }
    [Table]
    public class StringData
    {
        [Column(IsPrimaryKey = true)]
        public int Id { get; set; }
        [Column(DbType = "NVarChar(255) NOT NULL")]
        public String String { get; set; }
    }
    
  5. 首先,我不时地使用SubmitChanges()来处理InsertOnSubmitTour(),但这显然是一种缓慢的方式,因为SubmitChanges()每行插入一行。所以我尝试了SqlBulkCopy,它显然不适用于SQL Server Compact Edition,这让我最终使用了SqlCeBulkCopy,它看起来更快,但仍然很慢。

这个解决方案有两个问题:

  1. 它仍然很慢

  2. 生成的大小要大很多倍请注意,Belgium.osm.pbf只有~80 MB。然而,.sdf似乎是~592 MB,对此我能做些什么吗?

因此,以下是我的问题:

  1. 我哪里完全错了?我该怎么办

    我觉得很奇怪,很难正确处理一个80 MB的文件。还请注意,我现在正在我的电脑上进行所有这些计算,一旦它在电脑上运行正常,我会在Windows Phone 7上尝试。

  2. 如果真的没有方便的LINQ解决方案,那么生成索引PBF有意义吗

    然而,这需要我重新发明数据库已经可以提供给我的东西

  3. 增加我电脑的大小,实质上是编写一个转换器,然后将~592 MB的.sdf数据库文件发送到我的手机,这有意义吗

    这似乎是介于选项1和选项2之间的最后手段,但这并不能使应用程序上传到MarketPlace,因为必须提前在计算机上进行转换,然后以某种方式将其上传到手机上,这是非常令人讨厌的。

请注意,我专注于问题1,其他问题只是解决方案,如果这被证明是不可能的,我只是错过了一些可以让它变得流畅的东西,但我不知道。。。

为此使用数据库是有意义的。大小可能是由于pbf文件的紧凑性,还要记住SQL CE中的所有数据都是unicode。你的问题不清楚——什么是慢?此外,您可以尝试在导入后压缩数据库文件,这可能会使文件缩小一点。根据产生的大小,您的.xap可能仍然足够小,适合MarketPlace。(由于.xap也压缩了sdf文件)

最新更新