如何解决使用大型地址数据库进行自动建议的最佳方法是什么?
我有一个包含一个国家大约 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.
选择地址还要填写城市和邮政编码。
注意:这是在地址格式为 Street ##/##
的国家/地区,因此实际名称是第一个输入的内容。
执行一次 SELECT * FROM addresses WHERE street LIKE 'Count%' LIMIT 10
查询平均需要大约 3 秒。仅选择 street,house_number,city,zip
会稍微快一些。每行有 19 列。我已经根据一些 MysqL 指南在其中一列上添加了索引,但这并没有显着帮助。我希望每个请求的时间低于 500 毫秒。
解决方法
让我逐步完成分析。
- 您正在搜索以给定字符串开头的街道地址,对吗?
-
WHERE street LIKE 'Count%'
与INDEX(street)
一起是合理的最佳选择。没有单独的表,没有 JSON,没有首字母等。 -
LIMIT 10
将有效地找到前 10 个这样的项目。注意:添加ORDER BY
可能会影响性能。 -
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”的自动选择很可能会显示相同“1 Main St”的 10 个副本。
哦,我没有处理你从你的例子中暗示的东西。 street
包括街道号码。或者,您可能有两列 - street_name
(用于搜索)和 street_number
。所以...
有两列:
- 一个用于自动建议(“Main St”)
- 一个用于展示(“1 Main St,Acron OH”)
然后有INDEX(auto_suggest,display)
。这将为您提供获得自动建议值的最小工作效率,但允许同样有效地显示完整地址。
但这仍然存在重复地址的问题。好的,我现在不得不推荐一张额外的桌子。它将包含所有唯一街道名称,没有 street_number 等。
CREATE TABLE AutoSuggest (
street VARCHAR(99) NOT NULL,PRIMARY KEY(street)
) ENGINE=InnoDB;
请注意,在 MySQL 中,PRIMARY KEY
是与数据聚集的 B+Tree 索引,并且是 UNIQUE
。对于 200M 地址,此表可能大约为 1GB,在补偿了 dups、开销等之后。在您的应用程序运行一段时间后,大部分表将缓存在 buffer_pool 中。这使得典型的自动建议查找时间约为 1 毫秒。
但是,这只会给您街道名称,而不是地址等。也许您需要名为 full_street
的第二列(并更改为 PRIMARY KEY(street,full_street)
):
INSERT INTO AutoSuggest (street,full_street)
VALUES
("Main St","1 Main St");
这提供了前面提到的大部分好处和一些缺点。
用你的两个目标之间的权衡来思考我的评论:
- 快速自动建议;
- 自动建议期间 UI 呈现的内容。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。