1

我正在开发基于皇家邮政 PAF 数据的邮政编码查找的自定义构建软件。该软件的主要目的是取代快速地址(第三方软件供应商)。

我有几个问题

  1. 为什么包括索引在内的快速地址数据文件小于 500MB,而如果您查看 PAF 原始数据,它会超过 2.50GB。他们对原始数据执行了哪些清理和压缩技术来实现这一目标。我导入的 Db 大小是 2.50GB (sqlite)。我必须使用一些免费/开源 Db,而付费 Db 不是我的选择。

  2. 有 2800 万条记录。例如,考虑到可以使用“LIKE”语句执行搜索,我如何改进按组织名称或城镇的搜索?

任何的想法?

4

6 回答 6

0

文件大小对您来说是个问题吗?如果文件大小很重要,我只会担心压缩 - 它几乎不再这样做了,而且在大多数情况下,2.5 GB 并不是令人望而却步的。

如果你真的需要压缩数据,你几乎肯定不能使用现成的数据库系统;我猜 Quick Address 使用 ZIP 之类的东西来压缩数据。

至于第二个问题 - 你能举一个你的表的例子,以及你想要优化的查询类型吗?在大多数邮政编码查找系统中,唯一重要的查询是按邮政编码搜索并返回匹配的地址;只要您索引了邮政编码列,无论您有多少记录,这应该非常快。

于 2011-05-06T09:55:24.643 回答
0

您想尝试空间填充曲线或空间索引。sfc 将 2d 复杂度降低到 1d 复杂度。我用邮政编码搜索做了类似的事情。您想在 phpclasses.org (hilbert-curve) 上查看我的 sfc 的 php 实现。您想查找 Nick 的希尔伯特曲线四叉树空间索引博客。

对于 cityname 查找,您要查找 trie 数据结构。trie 是一种字典数据结构。您想在 phpclasses.org (kart-trie) 上查看我在 php 中的 kart-trie 实现。最坏情况的复杂度是 IMO log(n+k),其中 n 是字符串长度,k 是密钥长度。您希望将 kart-trie 转换为嵌套集,因为 kart-trie 与 radix-trie 或 crit-bit trie 不同,因此每个节点只有 2 个叶子。您想查找 php trie 和通配符http://phpir.com/tries-and-wildcards

于 2011-05-06T10:09:40.403 回答
0

不要存储您不需要的信息,例如 DPS、占用率和各种公司标志

与其保存 2800 万个地址,不如为每个邮政编码保存 180 万个地址,并为每个邮政编码(即门牌号、房屋/建筑物名称)提供一个分发点列表

我不确定您拥有哪个版本的 PAF、带键的关系版本或扩展版本。

键控版本将减小文件大小,因为您只需要由数字组成的地址指向位置、街道、街道末端等的查找表。但是在地址中使用键将无助于按组织或城镇名称进行搜索。

视图将帮助您从键格式化您的输出地址。确保您使用的数据库具有可以使用索引的视图,否则您将最终进行表扫描。

我过去所做的是使用全文搜索引擎 sphinx http://sphinxsearch.com/对 PAF 进行索引, 它可以对您决定索引的任何单词进行非常强大的搜索(包括部分单词和模糊匹配)。尝试地址中的所有单词。sphinx 的结果是一个键列表,可用于遍历 sql 结果集。sql 查询可以针对可用于从查找表构建完整地址的键的地址表。sphinx 索引构建速度非常快,并且生成的索引大小非常小。

对于这种大小的数据库,Mysql 可能比 sqlite 更适合。

其他要考虑的事情。您是在做批处理还是只是事务性的——忘记 sphinx 进行批处理。更新频率。如果您不每月更新,您将在很短的时间内变得过时。

注意:如果您有 PAF 的键控版本,则有一些用于格式化地址的可怕规则和许多未记录的异常。

于 2011-05-09T12:45:04.010 回答
0

我赞同 Tom Gurney 的观点……你做了很多工作却没有什么好处。此外,您还承担着随时更新数据的责任——额外的工作。

我假设您正在将邮政编码查找插入网站或内部应用程序?

有一些托管服务提供商可以为您完成这项工作,而且您的成本可能比直接访问皇家邮政要低,而且一旦集成,您几乎不需要动一根手指......

我为 CraftyClicks 工作,这是一家 PAF 解决方案提供商,所以在这里有一些既得利益..... http://www.craftyclicks.co.uk/

于 2011-06-08T09:47:22.320 回答
0

除了邮局的 PAF,您还可以使用 192.com 网站查找地址。

在过去的几个月里,我一直在成功地使用这种方法,并且没有遇到任何问题。

这是我的查找类。

    Imports System.Net
    Imports System.IO

    Public Class PCLookup
Property Addresses As List(Of Address)

Public Sub New(Postcode As String)
    GetAddresses(CreatDoc(Postcode))
End Sub

Private Function CreatDoc(PostCode As String) As mshtml.HTMLDocument
    Dim URL As String = FormatPostcode(PostCode)
    If URL = "" Then Return New mshtml.HTMLDocument
    Dim request As HttpWebRequest = WebRequest.Create(URL)
    Dim response As HttpWebResponse = request.GetResponse()
    Dim reader As StreamReader = New StreamReader(response.GetResponseStream())
    Dim doc As New mshtml.HTMLDocument
    Dim objDoc As mshtml.IHTMLDocument2 = doc
    Dim param As Object() = {reader.ReadToEnd()}
    objDoc.write(param)
    response.Close()
    reader.Close()
    Return objDoc
End Function

Private Function FormatPostcode(Postcode As String) As String
    Dim FullURL As String = "http://www.192.com/places/"
    Do Until Postcode.Contains(" ") = False
        Postcode = Replace(Postcode, " ", "")
    Loop
    If Len(Postcode) > 7 Or Len(Postcode) < 5 Then
        Return ""
    End If
    If Len(Postcode) = 5 Then
        FullURL &= Mid(Postcode, 1, 1) & "/"
        FullURL &= Mid(Postcode, 1, 2) & "-" & Mid(Postcode, 3, 1) & "/"
        FullURL &= Mid(Postcode, 1, 2) & "-" & Mid(Postcode, 3) & "/"
    End If
    If Len(Postcode) = 6 Then
        If IsNumeric(Mid(Postcode, 2, 1)) Then
            FullURL &= Mid(Postcode, 1, 1) & "/"
            FullURL &= Mid(Postcode, 1, 3) & "-" & Mid(Postcode, 4, 1) & "/"
            FullURL &= Mid(Postcode, 1, 3) & "-" & Mid(Postcode, 4) & "/"
        Else
            FullURL &= Mid(Postcode, 1, 2) & "/"
            FullURL &= Mid(Postcode, 1, 3) & "-" & Mid(Postcode, 4, 1) & "/"
            FullURL &= Mid(Postcode, 1, 3) & "-" & Mid(Postcode, 4) & "/"
        End If
    End If
    If Len(Postcode) = 7 Then
        FullURL &= Mid(Postcode, 1, 2) & "/"
        FullURL &= Mid(Postcode, 1, 4) & "-" & Mid(Postcode, 5, 1) & "/"
        FullURL &= Mid(Postcode, 1, 4) & "-" & Mid(Postcode, 5) & "/"
    End If
    Return FullURL
End Function

Private Sub GetAddresses(ObjDoc As mshtml.HTMLDocument)

    Dim Obj As mshtml.IHTMLElementCollection = ObjDoc.getElementsByTagName("td")
    Addresses = New List(Of Address)
    For Each TD As mshtml.HTMLTableCell In Obj
        If TD.className = "address" Then
            Dim FullAddress As String = TD.innerText
            Addresses.Add(New Address(FullAddress))
        End If
    Next

End Sub

    End Class

和地址类

    Public Class Address
Property Line1 As String
Property Line2 As String
Property Line3 As String
Property Line4 As String
Property Postcode As String
Public Sub New(FullAddress As String)
    Dim Obj As Object = Split(FullAddress, ", ")
    Select Case UBound(Obj)
        Case 4
            Line1 = Obj(0) & " " & Obj(1)
            Line2 = ""
            Line3 = Obj(2)
            Line4 = Obj(3)
            Postcode = Obj(4)
        Case 5
            Line1 = Obj(0) & " " & Obj(1)
            Line2 = Obj(2)
            Line3 = Obj(3)
            Line4 = Obj(4)
            Postcode = Obj(5)
        Case 6
            Line1 = Obj(0) & " " & Obj(1)
            Line2 = Obj(2) & " " & Obj(3)
            Line3 = Obj(4)
            Line4 = Obj(5)
            Postcode = Obj(6)
    End Select

End Sub
    End Class

我希望这对其他人有用。

富有的。

于 2012-06-12T15:40:04.507 回答
0

取决于您的具体要求。

频率:您可以获得一组一次性的数据文件,每年或每月,因此取决于您的数据需要保持多长时间。有一个带有 2 个城镇地址(约克和其他地方)的免费示例数据库可供试用并开始构建。

类型:您每次可以获得一整套数据文件,或者您必须自己应用更改的增量。

结构:正如 DGD 所说,您可以键控或扩展。

如果您需要新地址,使用增量,考虑到 RM 每月进行数千次更改,不仅仅是添加,而是删除、组合地址和转换(商业 <-> 住宅),将是大量的工作来申请自己. 特别是关于维护也可以在您自己的应用程序数据库中的其他地方使用的唯一地址密钥。

基于每月完整数据文件,扩展,包括新注册地址的'NotYetBuilt'文件,我构建了一个系统每月重新加载整个数据集,分为2部分:1.)下载最后一组数据,展开文件等,到磁盘和 2). 将新数据加载到数据库中

对于第 2 部分,当您加载数据时,您可以随时为每个条目构建一个完整的地址字符串(以返回搜索匹配项)。由于有超过 3100 万个地址,您不能使用 LIKE 或常规搜索语法。跨要用于搜索的字段构建 FULLTEXT 索引和存储过程以使用 CONTAINSTABLE for FREETEXT 进行搜索。

比我预期的更容易构建,困难在于:处理多个文件,每个文件有多达 31+ 百万条记录,当前和新地址在不同的文件中,没有“县”值(它们是从英国正式删除的2000 年的地址)它们位于不同的文件中,以便在需要时加载,等等。

于 2020-02-03T15:17:14.643 回答