gpt4 book ai didi

arangodb - 对ArangoDB文档集合进行重复数据删除

转载 作者:行者123 更新时间:2023-12-04 05:18:25 26 4
gpt4 key购买 nike

我敢肯定有一种简单快捷的方法可以做到这一点,但它却在逃避我。我有一个包含一些重复记录的大型数据集,我想摆脱这些重复记录。 (重复项由一个属性唯一标识,但文档的其余部分也应相同)。

我试图创建一个新集合,该集合仅以几种不同的方式具有唯一值,但它们的运行速度都很慢。例如:

FOR doc IN Documents
COLLECT docId = doc.myId, doc2 = doc
INSERT doc2 IN Documents2


要么

FOR doc IN Documents
LET existing = (FOR doc2 IN Documents2
FILTER doc.myId == doc2.myId
RETURN doc2)
UPDATE existing WITH doc IN Documents2


或(这给了我一个“违反唯一约束”错误)

FOR doc IN Documents
UPSERT {myId: doc.myId}}]}
INSERT doc
UPDATE doc IN Documents2

最佳答案

TL; DR

至少在我的台式机(Windows 10,Intel 6700K 4x4.0GHz,32GB RAM,Evo 850 SSD)上,不需要花费很长时间即可对记录进行重复数据删除并将其写入另一个集合(少于60秒)。

但是,某些查询需要正确的索引编制,否则它们将永远存在。索引需要一些内存,但与查询执行中用于对记录进行分组所需的内存相比,它可以忽略不计。如果内存不足,则性能会受到影响,因为操作系统需要在内存和大容量存储之间交换数据。对于旋转磁盘而言,这尤其是一个问题,而对于快速闪存存储设备则不那么重要。

制备

我生成了220万条记录,这些记录具有5-20个随机属性,每个属性有160个字符的乱码。此外,每个记录都有一个属性myid。 187k条记录具有唯一ID,60k myid存在两次,70k次存在3次。报告的集合大小为4.83GB:

// 1..2000000: 300s
// 1..130000: 20s
// 1..70000: 10s
FOR i IN 1..2000000
LET randomAttributes = MERGE(
FOR j IN 1..FLOOR(RAND() * 15) + 5
RETURN { [CONCAT("attr", j)]: RANDOM_TOKEN(160) }
)
INSERT MERGE(randomAttributes, {myid: i}) INTO test1


启动ArangoDB之前,启动4.0GB之后的内存消耗为3.4GB,加载 test1源集合后的内存消耗约为8.8GB。

基准线

test1读取并将所有文档(2.2m)插入 test2在我的系统上花费了20s,内存峰值约为17.6GB:

FOR doc IN test1
INSERT doc INTO test2


myid分组而不写,大约需要花费时间。对我来说是9s,在查询过程中RAM峰值为9GB:

LET result = (
FOR doc IN test1
COLLECT myid = doc.myid
RETURN 1
)
RETURN LENGTH(result)


分组失败

我对只有3条记录和一个重复的 COLLECT docId = doc.myId, doc2 = doc的数据集尝试了您的 myid方法。它表明查询实际上并未将重复项分组/删除。因此,我试图找到其他查询。

与INTO分组

要将重复的 myid分组在一起,但保留访问完整文档的可能性,可以使用 COLLECT ... INTO。我只是选择了每个组的第一个文档来删除多余的 myid。将2m条具有唯一 myid属性的记录写入到 test2的查询大约需要40秒钟的时间。我没有准确测量内存消耗,但是我看到了从14GB到21GB的不同内存峰值。可能由于某些陈旧的条目以某种方式(压缩/密钥生成)而阻塞了,所以删节测试集合并重新运行查询会增加所需的内存吗?

FOR doc IN test1
COLLECT myid = doc.myid INTO groups
INSERT groups[0].doc INTO test2


与子查询分组

以下查询显示更稳定的内存消耗,峰值为13.4GB:

FOR doc IN test1
COLLECT myid = doc.myid
LET doc2 = (
FOR doc3 IN test1
FILTER doc3.myid == myid
LIMIT 1
RETURN doc3
)
INSERT doc2[0] INTO test2


但是请注意,它需要 myidtest1上的哈希索引才能实现〜38s的查询执行时间。否则,子查询将导致数百万次集合扫描,并且需要花费一定时间。

与INTO和KEEP分组

我们可以只将 _id分配给变量,然后将其分配给 KEEP,而不是将所有文档归为一组,这样我们就可以使用 DOCUMENT()查找文档正文:

FOR doc IN test1
LET d = doc._id
COLLECT myid = doc.myid INTO groups KEEP d
INSERT DOCUMENT(groups[0].d) INTO test2


内存使用:加载源集合后为8.1GB,在查询过程中达到峰值13.5GB。 200万条记录仅用了30秒!

与INTO和投影分组

除了好奇心,我还出于好奇而尝试了一种预测:

FOR doc IN test1
COLLECT myid = doc.myid INTO groups = doc._id
INSERT DOCUMENT(groups[0]) INTO test2


加载 test1后,RAM为8.3GB,峰值为17.8GB(在查询执行过程中实际上有两个高峰,两个都超过17GB)。 200万张唱片用了35秒钟完成。

增补

我尝试使用UPSERT做一些尝试,但是看到了一些奇怪的结果。事实证明这是对ArangoDB的ups实施的监督。 v3.0.2 contains a fix,现在我得到正确的结果:

FOR doc IN test1
UPSERT {myid: doc.myid}
INSERT doc
UPDATE {} IN test2


myid中的 test2上使用(唯一)哈希索引处理需要40秒钟,RAM峰值约为13.2GB。

就地删除重复项

我首先将所有文档从 test1复制到 test2(2.2m条记录),然后尝试 REMOVE仅复制 test2中的副本:

FOR doc IN test2
COLLECT myid = doc.myid INTO keys = doc._key
LET allButFirst = SLICE(keys, 1) // or SHIFT(keys)
FOR k IN allButFirst
REMOVE k IN test2


内存为8.2GB(仅加载 test2),在查询过程中高达13.5GB。删除副本大约需要16秒钟(200k)。

验证

以下查询将 myid分组在一起,并汇总每个ID出现的频率。针对目标集合 test2运行,结果应为 {"1": 2000000},否则仍存在重复项。我仔细检查了上面的查询结果,并检查了所有内容。

FOR doc IN test2
COLLECT myid = doc.myid WITH COUNT INTO count
COLLECT c = count WITH COUNT INTO cc
RETURN {[c]: cc}


结论

对于ArangoDB v3.0,该性能似乎是合理的,尽管如果没有足够的RAM可能会降低性能。不同的查询大致在同一时间完成,但是显示出不同的RAM使用特性。对于某些查询,索引是避免高计算复杂性所必需的(这里:完全集合扫描;在最坏的情况下为2,200,000,000,000,000次读取?)。

您可以在数据上尝试我介绍的解决方案并检查计算机的性能吗?

关于arangodb - 对ArangoDB文档集合进行重复数据删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37704101/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com