【问题标题】:Searching strategy to efficiently load data from service or server?搜索策略以有效地从服务或服务器加载数据?
【发布时间】:2016-08-23 01:39:03
【问题描述】:

这个问题不是一个语言特定的问题,它是某种与模式相关的问题,但我想在这里用一些我能理解的流行语言标记它。

我对结合搜索数据(尤其是移动环境)有效加载数据的要求不是很有经验。

我之前使用的策略是将所有内容加载到本地内存并从那里搜索(例如在 C# 中使用 LINQ)。

另一种策略是每次执行新搜索时重新加载数据。这样做当然效率不高,而且我们可能需要做一些更复杂的事情来将新加载的数据与现有数据(已经加载到本地内存)同步。

我能想到的最后一个策略是最难实现的,即延迟加载数据和搜索执行。也就是执行搜索的时候,返回结果应该缓存在本地。在从服务/服务器获取新结果之前,搜索应该首先查看本地内存。所以每次搜索的结果都是本地搜索和服务器搜索的组合。此处的目的是减少每次运行搜索时从服务器重新加载的数据量。

这是我能想到的实施这种策略的方法:

  • 运行搜索时,首先查看本地内存。完成这一步会给出本地结果。
  • 现在,在向服务器端发送搜索请求之前,我们需要以某种方式传递已经放入结果中的内容(本地),以便在服务器端搜索时将它们从结果中排除。因此,搜索方法可能包括一个参数列表,其中包含第一个步骤找到的所有项目 ID。 通过该搜索请求,我们可以排除找到的结果并仅将新项目返回给客户端。
  • 最后一步是合并 2 个结果:从本地和服务器获得最终搜索结果,然后在 UI 上显示给用户。

我不确定这是否是正确的方法,但我觉得这里不是很好的是第 2 步。因为我们需要将第 1 步中找到的项目 ID 列表发送到服务器,所以如果我们有成百上千个这样的 ID,在这种情况下将它们发送到服务器可能效率不高。此外,排除如此大量项目的查询也可能效率不高(即使使用直接 SQL 或 LINQ)。在这一点上我仍然感到困惑。

最后,如果您有更好的想法并在某些生产项目中得到重要实施,请与我分享。我不需要任何具体的示例代码,我只需要一些想法或步骤来实现。

【问题讨论】:

  • 每当您感兴趣的内容发生变化时,我都会发送一条消息,这样您就可以使您的内存副本保持最新,并且始终保持内存速度。
  • 我想知道这个问题是否会在Programmers Stack Exchange 上得到更好的解决,因为它对于这个站点来说似乎有点宽泛——但这并不能保证它会在那里得到更好的解决。请阅读What is the difference between stackoverflow and programmers.stackexchange?Choosing between Stack Overflow and Programmers Stack Exchange 了解更多信息。
  • @PeterLawrey 我不确定我在这里感兴趣的内容是否可以事先知道,因为搜索是根据用户键入的关键字按需运行的。这意味着理论上所有的项目都是我感兴趣的(因为用户可以搜索/找到其中任何一个)。所有项目可能占用数百甚至数千 MB。谢谢。
  • 正确,您可能需要几 GB 的内存。对于服务器来说,这是相当正常的事情。通过与客户端的慢速连接下载几 GB 并不是一个好主意,但也不是直接从客户端联系数据库。我建议你有一个靠近数据库的服务,它缓存你需要的所有数据,你有一个向它发送查询的客户端。顺便说一句,16 GB 的成本约为 100 美元。
  • @PeterLawrey 所以你的意思是搜索是针对具有一些缓存数据库的服务器运行的。恐怕我没有这么专用的服务器。不管怎样,谢谢你的分享,真的很有帮助。

标签: java c# performance search design-patterns


【解决方案1】:

评论太长了......

关于第 2 步,你知道你会遇到很多问题:

数据量

随着时间的推移,您可能会积累大量数据,以至于即使设置它们的 id 也比正常的服务器答案大。最后,您可能不仅需要在客户端缓存以前服务器的答案,还需要在服务器上缓存客户端的状态。您正在做的是某种同步,因此请查看rsync 以获得灵感;这是一个古老但智能的 Unix 工具。 git push 也可能会鼓舞人心。

基本上,通过将 ID 组织成树,您可以轻松地在服务器和客户端之间同步信息(关于客户端已经知道的信息)。由于可能需要多个步骤,因此代价可能会增加延迟。

运用知识

很有可能从 SQL 结果中排除已知对象可能比不排除更昂贵,尤其是当您无法轻松确定要排除的对象是否是完整答案的一部分时。不过,您可以通过对数据进行后过滤来节省带宽。

及时更新

如果您的数据发生更改或被删除,您可能会发现您的客户保留了过时的数据。客户订阅相关更改是一种可能性;将(逻辑)时间戳与您的 ID 相关联是另一种方法。

总结

它可能会变得非常复杂,您应该在尝试之前进行测量。您可能会发现问题本身已经够难了,实现这些节省更加困难,而且收益有限。你知道root of all evil,对吧?

【讨论】:

  • 感谢您的回答,虽然它没有解决或为我的问题提供任何解决方案,但它确实指出了我应该考虑的一些事情,+1 为您提供有用的分享。
【解决方案2】:

我会认为本地和远程是两个不同的数据源来解决这个问题,

  1. 触发搜索时,将针对两个数据源(本地 - 内存和服务器)启动搜索

  2. 本地搜索最有可能首先产生结果,因此将结果显示给用户。

  3. 从服务器返回结果时,可以追加不重复的结果。

  4. 可选 - 如果服务器数据已更改并且某些结果已删除/或已更改,请更新/删除本地结果并更新视图。

【讨论】:

  • 好吧,我认为您的方法在某些情况下有效,但是如果我们需要对整个结果进行排序或分组怎么办?所以合并步骤应该在显示任何东西之前完成。无论如何,现在我认为我想要实现的是相当复杂的东西,不应该使用,使用一些专用服务器(作为缓存)可能是我们应该遵循的(当然它需要更多的硬件和金钱)。但是,我想为您分享的内容给您 1 票 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-12-19
  • 2015-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-05
  • 2014-02-11
相关资源
最近更新 更多