将一大组数据与另一大数据进行比较的绝对最快方法是什么?

时间:2016-01-18 21:22:22

标签: database sorting dataset compare

你有一个很大的独特项目列表(数十万行)。您想要查看这些项目是否存在于另一组数据中。另一组数据只是一个包含逐行项目的文件,也是一组唯一的数据。您可以将任何数据放入数据库,使用任何编程语言等。

你怎么做才能比较这些最快?唯一的限制是硬件是普通服务器,而不是数据库服务器。最多一个主轴

C 2实现排序算法? DB用于索引等?

管理员拿出了我的回答“因为问题太广泛了”:Bloom过滤器在python中。使用python的bloom过滤器库实现起来非常简单。

2 个答案:

答案 0 :(得分:1)

您可以使用简单的bash脚本:

首先对列表进行排序

$ sort list1.txt > list1.sorted.txt
$ sort list2.txt > list2.sorted.txt

然后进行连接以找到两个列表的公共元素:

$ join -1 1 -2 1 list1.sorted.txt list2.sorted.txt

这应该相对较快并且内存消耗较低。

答案 1 :(得分:1)

如果你的"测试" file有一个合理的大小,一个快速的解决方案是为该文件中的每个条目构建一个哈希映射。 C#解决方案(在Big O(N)中运行)是:

public static bool SetIsPresentIn(string firstFileLocation, string secondFileLocation)
        {
            HashSet<string> set = new HashSet<string> ();

            using (var sr = new FileStream(firstFileLocation, FileMode.Open, FileAccess.Read))
            {
                using (var reader = new StreamReader(sr))
                {
                    while (reader.EndOfStream == false )
                    {
                        var text = reader.ReadLine();
                        set.Add(text);
                    }
                }
            }

            // iterating through the first one!

            using (var secondFile = new FileStream(secondFileLocation, FileMode.Open, FileAccess.Read))
            {
                using (var reader = new StreamReader(secondFile))
                {
                    while (reader.EndOfStream == false)
                    {
                        var line = reader.ReadLine();
                        // perform a lookup!

                        if (set.Remove(line) && set.Count == 0)
                            return true;

                    }
                }
            }

            return set.Count == 0;
        }

否则我会做一个聪明的事情:分开你的&#34;测试&#34;文件分区中的文件:每个分区名称与每行的哈希码匹配。迭代第二个文件时,只需创建一个哈希码并在第一个文件构建的相应分区内搜索!

示例:

public static bool SetIsPresentInUsingFilePartitions(string firstFileLocation, string secondFileLocation, string partitionsRootLocation)
        {
            Dictionary<int, StreamWriter> partitionWriters = new Dictionary<int, StreamWriter>();

            Dictionary<int, string> locations = new Dictionary<int, string>();
            using (var sr = new FileStream(secondFileLocation, FileMode.Open, FileAccess.Read))
            {
                using (var reader = new StreamReader(sr))
                {
                    while (reader.EndOfStream == false)
                    {
                        var text = reader.ReadLine();
                        var hCode = text.GetHashCode();


                        var fileName = Path.Combine(partitionsRootLocation, hCode.ToString ());

                        if (false == partitionWriters.ContainsKey(hCode))
                        {
                            var fs = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite);
                            partitionWriters[hCode] = new StreamWriter(fs);
                            locations[hCode] = fileName;
                        }

                        partitionWriters[hCode].WriteLine(text);
                    }
                }
            }

            // close writers 
            foreach (var item in partitionWriters)
                item.Value.Dispose();


            using (var sr = new FileStream(firstFileLocation, FileMode.Open, FileAccess.Read))
            {
                using (var reader = new StreamReader(sr))
                {
                    while (reader.EndOfStream == false)
                    {
                        var line = reader.ReadLine();
                        var hCode = line.GetHashCode();

                        string location;
                        if (false == locations.TryGetValue(hCode, out location))
                        {
                            return false; // tere's a line that is not found in the second file!

                        }

                        var found = false;
                        using (var file = new FileStream(location, FileMode.Open, FileAccess.Read))
                        {
                            using (var fs = new StreamReader(file))
                            {
                                while (fs.EndOfStream == false)
                                {
                                    var firstFileLine = fs.ReadLine();
                                    if (line == firstFileLine)
                                    {
                                        found = true;
                                        break;
                                    }

                                }
                            }


                        }

                        if (!found)
                            return false;
                    }
                }

            }

            return true;

        }