【发布时间】:2010-11-01 13:06:13
【问题描述】:
在 html 输入框中实现自动完成功能的服务器端组件的快速有效方法是什么?
我正在编写一个服务来在我们的 Web 界面的主搜索框中自动完成用户查询,并且完成显示在一个 ajax 驱动的下拉列表中。我们正在运行查询的数据只是我们系统知道的一个大型概念表,它与维基百科页面标题的集合大致匹配。对于这项服务,速度显然是最重要的,因为网页的响应性对用户体验很重要。
当前的实现只是将所有概念以有序集合的形式加载到内存中,并在用户击键时执行简单的 log(n) 查找。然后使用尾集来提供最接近匹配之外的其他匹配。这个解决方案的问题是它不能扩展。它目前正在运行虚拟机堆空间限制(我设置了 -Xmx2g,这大约是我们可以在 32 位机器上推送的最多),这阻止了我们扩展概念表或添加更多功能。在具有更多内存的机器上切换到 64 位 VM 并不是一个直接的选择。
我一直犹豫是否要开始使用基于磁盘的解决方案,因为我担心磁盘寻道时间会影响性能。是否有可能的解决方案可以让我更好地扩展,无论是完全在内存中还是通过一些快速的磁盘支持实现?
编辑:
@Gandalf:对于我们的用例,重要的是自动完成功能是全面的,而不仅仅是对用户的额外帮助。至于我们正在完成什么,它是一个概念类型对的列表。例如,可能的条目是 [("Microsoft", "Software Company"), ("Jeff Atwood", "Programmer"), ("StackOverflow.com", "Website")]。一旦用户从自动完成列表中选择了一个项目,我们就会使用 Lucene 进行完整搜索,但我还不确定 Lucene 是否能很好地用于自动完成本身。
@Glen:这里没有使用数据库。当我谈论表格时,我只是指我的数据的结构化表示。
@Jason Day:我对这个问题的最初实现是使用Trie,但由于需要大量对象引用,因此内存膨胀实际上比排序集更糟糕。我将阅读三元搜索树,看看它是否有用。
【问题讨论】:
-
你能告诉我们更多关于你“自动完成”的信息吗?为什么这么多术语?是否有更明显的查询可以满足 90% 的用户查询,而不是加载所有可能性?
-
我不能确定 Lucene 是否能满足您的需求,但在那个大小的数据集上,我非常怀疑您不会在优化的 Lucene 索引上获得亚秒级的查询时间。根据索引的设置方式,您甚至可以将其存储在内存中。
-
一个标准的 Trie 确实是非常占用内存的,对于更大的集合,你想使用一个压缩的 Trie,它可以大大减少内存占用。其他优化包括节点值的延迟初始化和子/值集的正确数据结构。不久前,我创建了一个 Java autocomplete library 能够处理非常大的数据集(10,000,000+)并有效地回答精确和近似搜索。
标签: java memory autocomplete performance