我在一个MSSQL(主数据)中有大约600万条记录
在一个elasticsearch中约有600万条记录
我想从elasticsearch中删除数据库中不存在的记录。
当我在java中使用两个ArrayList时,它非常慢。在左手边还有一个TreeMap。我已经将超时时间增加到10分钟,但它不会在此期间内完成。在java中有什么更快的选项吗?
如果没有更快的选择,可以为此创建一个mssql表,让mssql处理diff操作。
如果一个elasticsearch有600万个clauses,可以使用“delete by query”吗?我可以只为一个query增加很多clauses吗?最好是通过url query param或者在请求体中?
3条答案
按热度按时间c7rzv4ha1#
在ES中执行可能是最快的,而数据库也能够非常快地执行此操作,您必须通过网络多次发送数据。
当在Java中这样做时,你需要考虑所有方法和你使用的数据结构的复杂性(因为两个列表的大小相当,为了简单起见,我假设它们的大小n相同):
2使用removeAll()或类似简单方法的列表
使用2个列表(这里甚至不讨论ArrayLists)意味着时间复杂度为O(n^n)。
DB数据的TreeMap
如果对DB数据使用TreeMap,对ES数据使用列表,那么时间复杂度为O(n * log(n))
然而,列表结构在这里也发挥了作用:从ArrayList中删除元素会导致数据移动,即使你向后迭代。然而,你并不需要快速随机访问该列表,所以LinkedList会更好。
另外,使用HashMap而不是TreeMap可以改善时间,因为这基本上将构建Map变成O(n),并且也将查找变成O(n)(如果Map配置了正确的大小,则列表迭代为O(n),查找为O(1))。它将使用更多的内存,并且不允许重复(但TreeMap也不允许),因此需要考虑这一点。
示例:
使用2个排序列表
如果你不能使用HashMap,你可以尝试使用2个排序列表,并同时推进它们。如果你可以从ES和DB中获得预排序的列表,那么这将具有O(n)的复杂度,否则你需要首先对它们进行排序,这将使其变成O(n * log(n))。
当你对列表进行排序时,你基本上是同时迭代它们两个,应用以下逻辑:
示例:
pengsaosao2#
潜在解决方案:mssql DB触发器,将物理删除记录的ID放入新表+某个日期。
然后,由企业集成模式“轮询消费者”+ REST API触发的新作业将从DB中收集接下来的60.000个(默认最大子句为65xxx)ID,并通过delete by query从elasticsearch中删除它们。
ccrfmcuu3#
使用ArrayLists或TreeMaps比较内存中的两个大型数据集可能会很慢且效率低下。提高性能的一个选项是使用数据库连接操作来比较记录。您可以在SQL Server中创建一个临时表并将Elasticsearch数据加载到其中,然后与主数据表执行连接以识别Elasticsearch表中不存在的记录。一旦识别出要删除的记录,你可以使用Elasticsearch“delete by query”API来删除它们。
如果你想用600万个子句执行“delete by query”操作,这可能不是一个可行的解决方案,因为它会导致性能问题,并可能导致Elasticsearch集群崩溃。相反,你可以将删除操作分解成更小的批次,并使用Elasticsearch Scroll API一次检索记录的子集并删除它们。
总的来说,使用SQL Server和Elasticsearch操作的组合可以帮助您有效地比较和删除两个数据集之间的记录。