数据结构论坛

首页 » 分类 » 常识 » GUID树数据结构模型以及建模分析
TUhjnbcbe - 2023/7/5 20:14:00

介绍

通过现代数据分析,我们遇到了数十亿条记录的情况,每条记录都有自己的GUID。我们如何组织数TB的数据并检索我们想要的内容?

我描述的解决方案使用GUID作为密钥,但可以使用更通用的解决方案。

背景

在我以前的公司工作时,有人提到他们有数十亿条记录需要处理。他们想要计算唯一GUID的数量,但找不到有用的工具。这个想法突然出现在我脑海里,结果就是这样。

该解决方案基于具有m个数字的基本n键的概念。在GUID的情况下,我们有32个十六进制数字。因此,我们可以创建深度为32的树结构(对于GUID中的每个数字)。每个节点都有一个包含16个子树的数组。

下面是一个简化的例子:

在A下,在根目录下,数组包含3个元素,链接到3个子树。该System.Guid方法ToByteArray返回一个16字节的字节数组。由于一个字节包含个可能的值,这似乎是不必要的内存使用。因此,我将其拆分为32个元素的字节数组,其中每个元素都包含一个十六进制值。这允许具有包含16个子树的阵列的节点而不是个子树。我可以使用链表而不是数组,但我不想增加检索时间。为了表现,我牺牲了记忆力。提供的解决方案使用两种类型的数据结构,具体取决于您需要存储的记录数。

基于记忆

对于小数据集,当我们确定所有数据都可以存储在内存中时。这里使用上述数据结构。

基于文件

对于由数十亿条记录组成的大型数据集。该解决方案使用文件系统来存储数据。上述数据结构表示为一系列文件系统目录。限制是您需要具有足够内存的驱动器。您需要使用跨区硬盘来存储您需要使用的所有数十亿条记录。这是目前的单线程,尽管可以使用多线程解决方案。

使用代码

对于内存中的解决方案:

//Createcollectionformemory-basedstorageGuidCollectionintguidCollection=newGuidCollectionint();//KeywewilluseGuidnewGuid=Guid.NewGuid();//AddguidCollection.Add(newGuid,5);//Containskeyboolres=guidCollection.ContainsKey(newGuid);//Countintcount=guidCollection.guidArrayTree.Count;//AllowoverwritingdataguidCollection.OverwriteValues=true;//Index(set)guidCollection[newGuid]=10;//Index(get)intval=guidCollection[newGuid];//Enumerateforeach(intintValinguidCollection.GetEnumerator()){System.Console.WriteLine(Valueis:+intVal);}//RetrieveintretrivedValue;guidCollection.TryGetValue(newGuid,outretrivedValue);//RemoveguidCollection.Remove(newGuid);

对于基于文件的解决方案:

//directorywherewestorethedatastructurestringdir=C://TestDir/;//Createcollectionforfile-basedstorageGuidCollectionintguidCollection=newGuidCollectionint(dir);//KeywewilluseGuidnewGuid=Guid.NewGuid();//AddguidCollection.Add(newGuid,5);//Containskeyboolres=guidCollection.ContainsKey(newGuid);//Countintcount=guidCollection.guidArrayTree.Count;//AllowoverwritingdataguidCollection.OverwriteValues=true;//Index(set)guidCollection[newGuid]=10;//Index(get)intval=guidCollection[newGuid];//Enumerateforeach(intintValinguidCollection.GetEnumerator()){System.Console.WriteLine(Valueis:+intVal);}//RetrieveintretrivedValue;guidCollection.TryGetValue(newGuid,outretrivedValue);//RemoveguidCollection.Remove(newGuid);

兴趣点

该GetEnumerator()方法需要递归,因为我们正在处理深度嵌入的数据结构,并且每个级别都有多个条目,添加和检索数据是线性时间。但是,我们在内存使用方面付出了代价。

1
查看完整版本: GUID树数据结构模型以及建模分析