我正在阅读日志文件。
我的目标是显示网站上最受欢迎的10个网址。
执行此操作的一种方法是读取所有日志条目并将每个URL保存到Dictionary。字典将URL作为密钥,将访问次数作为值。如果字典中存在URL,则该URL的Key的值增加+1,否则添加值为1的新Key / Value对。
处理完成后,字典按值排序,并显示前10个条目。
这可能会有效,但是当处理具有数千个不同页面网址的网站的日志文件时(考虑查询字符串),它可能会导致严重的内存问题。
由于我只需要前10个条目,是否有办法避免将所有网址放入内存并仍然获得前10个网址+访问次数?
答案 0 :(得分:5)
对于大多数理智的数据集,这不会导致严重的内存问题 除非您在Google工作,否则您不会遇到任何内存问题 过早的优化是邪恶的。
如果在实现它之后,只有内存问题,则应切换到SQL数据库。
编辑 :(回复您的评论)
10,000个不同的500个字符的字符串将使用10,000 * 500 * 4个字节= 20MB,这非常少。 (它还会更多地用于字符串管理和字典本身,但总共不到1MB)
在您开始获得数百万个唯一 500个字符的网址之前,您无需担心。
答案 1 :(得分:0)
创建前10个网址的准确图表,没有。 但是,你可以做的是抽样,或者摆脱那些没有机会进入前10名的网页,例如,缓存每一页的访问一天,只跟踪前100页,除此之外,你' d需要存储每个页面的访问次数。
答案 2 :(得分:0)
如果你可以将它全部放入一个字典中,那就去做吧。
...但是我们假设你的日志文件有太多的URL不适合单个字典。
Dict0(URL) = count
。RevDict0(Count) = {URL0,URL1,...}
在VB.Net中,这里是如何反转字典:
Dim RevDict0 as Dictionary(of Integer, List(of String))
For Each url as String in Dict0
If Not RevDict0.Contains(Dict0(url)) Then
RevDict0.Add(Dict0(url), new List(of String))
End If
RevDict0(Dict0(url)).Add(url)
Next
现在看一下RevDict0的第11个索引RevDict0.Keys.Sort.Reverse.item(11)
。例如,假设该数字为90.现在关闭日志文件和字典以释放内存,然后使用日志文件的后半部分再次启动以生成Dict1和RevDict1。检查RevDict1.Keys.Sort.Reverse.Item(11)
。让我们假设这个数字是40.现在我们知道上半场任何不到50次访问的URL都不能超过90次访问(50 + 40)所以它不会超过90次访问不可能进入最后十强。
现在我们释放除了RevDict1
的前十名以外的所有内容。
现在:
FinalDict(of String, Integer)
(如果您之前存储了Dict0,则从磁盘读取)。FinalDict
中删除不在RevDict1中的少于50次访问的内容,以释放内存。FinalDict
。注意:
FinalDict
个成员,它只会节省内存。