使用用于自动建议的庞大地址数据库的最佳方式是什么?

What is the best way to work with a huge address database for autosuggest?

我有一个数据库,其中包含一个国家/地区的大约 300,000,000 个地址。此数据应该用于表格中的自动建议,即:如果地址是 1900 Country Hill Road,用户将键入 Count(假设至少 3 个字符来触发自动建议是个好主意) ,并且表单可能会为用户提供前 10 个结果,即:

165 Countable Road
1890 Countable Road
44 Counting Circle
900 Country Drive
13 Country Hill Road
1900 Country Hill Road
344 Country Mountain Place
etc.

选择地址还要填写City和ZIP。 注意:这是在地址格式为 Street ##/## 的国家/地区,因此首先要输入实际姓名。

执行 SELECT * FROM addresses WHERE street LIKE 'Count%' LIMIT 10 查询平均需要大约 3 秒。仅选择 street, house_number, city, zip 会稍微快一些。每行有 19 列。我已经根据一些 MySQL 指南在其中一列上添加了索引,但这并没有显着帮助。我希望每个请求的时间少于 500 毫秒。

解决此问题的最佳方法是什么?我想到的是:

让我逐步分析。

  1. 您正在搜索街道地址开头的给定字符串,正确吗?
  2. WHERE street LIKE 'Count%'INDEX(street) 是合理的最佳选择。没有单独的table,没有JSON,没有首字母等
  3. LIMIT 10 将有效地找到前 10 个这样的项目。注意:添加 ORDER BY 可能会破坏性能。
  4. SELECT street 在索引的 B+Tree 中找到结果。由于这就是您所需要的,因此请使用它。 SELECT <<some columns>>SELECT * 必须执行额外操作才能获取其他列。

这样的索引会向下钻取 B+Tree 到第一次出现的“Count...”,然后从那里向前扫描。即使数据集不能缓存在 RAM 中,实际上也只有一次磁盘命中,这将花费几毫秒。如果您需要额外的列,那么额外的操作可能需要 10 次以上的磁盘命中(由于 LIMIT 10)。

因此,重要的是 INDEX 包含 完全 您需要接收的 自动建议

ORDER BY 可以 只有当 你说 ORDER BY street(或 ORDER BY street DESC)。否则,它必须找到以“count”开头的数千(百万?)条街道,对这个列表进行排序,然后交付 10。

根据该分析,“最少 3 个字符”并不重要。然而,我的 UI 直觉是 3 是合理的。

哦,另一个问题。由于数千个城镇中可能有“1 Main St”,因此“Main”的自动 select 可能会显示 10 个相同的“1 Main St”。

哦,我没有处理你从你的例子中暗示的东西。 street 包括街道号码。或者您可能有两列——street_name(用于搜索)和 street_number。所以...

有两列:

  • 一个用于自动建议(“Main St”)
  • 一个用于展示(“1 Main St, Acron OH”)

然后有INDEX(auto_suggest, display)。这将使您以最少的努力获得自动建议值的效率,但允许同样有效地显示完整地址。

但这仍然存在重复地址的问题。 OK,我现在被迫额外推荐一个table。它将包含所有 唯一 街道名称,没有 street_number,等等

CREATE TABLE AutoSuggest (
    street VARCHAR(99) NOT NULL,
    PRIMARY KEY(street)
) ENGINE=InnoDB;

注意,在MySQL中,一个PRIMARY KEY是一个B+Tree索引,与数据聚簇,是UNIQUE。对于 200M 地址,这个 table 可能大约是 1GB,在补偿重复、开销等之后。在你的应用程序有 运行 一段时间后,大部分 table 将被缓存在 buffer_pool。这使得典型的自动建议查找大约需要 1 毫秒。

但是,这只会给你街道名称,而不是地址等。也许你想要一个名为 full_street 的第二列(并更改为 PRIMARY KEY(street, full_street)):

INSERT INTO AutoSuggest (street, full_street)
    VALUES
    ("Main St", "1 Main St");

这提供了前面提到的大部分优点和少数缺点。

考虑我对您的两个目标进行权衡的评论:

  • 快速自动建议;
  • UI 在自动提示期间呈现的内容。