C#中List占用很大内存

happy819 2021-01-13 10:58:42
我要读取数据库的数据,有1000万行左右,只有一个字符串字段,每条数据差不多10个字符,读出来放到list里后发现程序占用内存巨大,差不多600多M,有没有内存占用少的方法?读出来后主要的操作就是查找某个字符串是否在list中。
...全文
5377 52 打赏 收藏 转发到动态 举报
写回复
用AI写文章
52 条回复
切换为时间正序
请发表友善的回复…
发表回复
socg 2021-04-02
  • 打赏
  • 举报
回复
数据的内容摆在那里,你想减少内容,只有把数据放出去,放在文件或数据库里,其实数据库查询也不会太慢
jhonsonzhang 2021-03-26
  • 打赏
  • 举报
回复
使用EF6或者EFcore.查询语句用linq。应该不存在这个问题。至少远高于list<string>。不想太多改变,加个异步任务去比对更新,主线程只管爬。这样进程就快。本身也该这样做。
超哥哥哇 2021-03-25
  • 打赏
  • 举报
回复
你这需求一般在处理大数据量的时候才会用到的,也就是缓存机制,你想提高效率,是可以这么做的,把一部分数据读取到内存中,然后在用户请求时直接访问内存效率会提升很多。可以考虑使用构造函数。目前.netcore中使用的缓存机制比较成熟,可以考虑使用IMemoryCache,谢谢
余山水 2021-03-25
  • 打赏
  • 举报
回复
多线程,每个线程读10个或者100分块读取更合适,
SayoKun 2021-03-23
  • 打赏
  • 举报
回复
我怎么感觉这个问题似曾相识,去年好像也有人问过。
tttexas 2021-03-22
  • 打赏
  • 举报
回复
实在想用内存的话,可以高一个内存数据库,把数据进库再sql,速度和效率兼得。
枫雁 2021-03-21
  • 打赏
  • 举报
回复
不知道楼主是否学过数据库编程,是专门的数据库编程,而不是调用数据这种。

大数据优化的问题,要在数据服务器端来进行解决,写过程,客户端传入参数取出数据。
在服务端查询筛选的优点是,1、过程的版本更新不用客户端改代码 2、在服务端查询更快,因为查询时不用交互,返回数据不占用网络资源。

总之,数据多用过程。
MuteG 2021-03-19
  • 打赏
  • 举报
回复
引用 43 楼 橘子皮zzz 的回复:
[quote=引用 38 楼 MuteG 的回复:]可以用List<int>来保存字符串的GetHashCode结果,这个每个字符串的特征码就只占4个字节,1000万条记录,占用空间才几十M。



Dim a As New List(Of String)
For i = 1 To 10000000
a.Add(RndName)
Next
a.Add("ilovecsdn")

Dim t As Integer = GetTickCount()
Dim pd As Boolean = a.Contains("ilovecsdn")
msgbox(pd.ToString & vbCrLf & (GetTickCount() - t))



Dim a As New List(Of String)
For i = 1 To 10000000
a.Add(RndName)
Next
a.Add("ilovecsdn".GetHashCode )

Dim t As Integer = GetTickCount()
Dim pd As Boolean = a.Contains("ilovecsdn".GetHashCode )
msgbox(pd.ToString & vbCrLf & (GetTickCount() - t))


为什么我测试的用gethashcode反而慢了一倍的时间??? 前者是47毫秒后者是74毫秒[/quote]

不知道你的运行效率对比执行了多少次,如果只是看单次执行的结果来进行对比,这样是不准确的。
另外,你的特征码集合是 String 类型,但是 GetHashCode 返回的是 int,这里会出现一个类型转换,这个操作也会稍微耗时。
还有,如果做这种特征码判断,不应该使用 List,而是该用 HashSet,时间复杂度是 O(n) 和 O{1) 的差距。
请参考我的代码:

private const int DATA_COUNT = 10000000;
public void Execute()
{
var stringSet = new HashSet<string>(DATA_COUNT);
var hashCodeSet = new HashSet<int>(DATA_COUNT);
for (int i = 0; i < DATA_COUNT; i++)
{
var s = Guid.NewGuid().ToString();
stringSet.Add(s);
hashCodeSet.Add(s.GetHashCode());
}

var target = Guid.NewGuid().ToString();
stringSet.Add(target);
hashCodeSet.Add(target.GetHashCode());

int stringSize = Encoding.ASCII.GetByteCount(target) * (DATA_COUNT + 1);
int hashCodeSize = sizeof(int) * (DATA_COUNT + 1);

var stopwatch = new Stopwatch();
stopwatch.Start();
for (int i = 0; i < DATA_COUNT; i++)
{
stringSet.Contains(target);
}

stopwatch.Stop();
Debug.WriteLine($@"String > Size : {stringSize:N0}, Cost : {stopwatch.ElapsedMilliseconds} ms");

stopwatch.Restart();
for (int i = 0; i < DATA_COUNT; i++)
{
hashCodeSet.Contains(target.GetHashCode());
}

stopwatch.Stop();
Debug.WriteLine($@"HashCode > Size : {hashCodeSize:N0}, Cost : {stopwatch.ElapsedMilliseconds} ms");
}


这是我的执行结果:
String > Size : 360,000,036, Cost : 421 ms
HashCode > Size : 40,000,004, Cost : 360 ms
结论是不仅空间占用有 9 倍的差距,消耗时间也是利用 GetHashCode 更优(一千万次执行总耗时)。
失落的神庙 2021-03-09
  • 打赏
  • 举报
回复
用字典类型吧,然后用10个来分片存储,分片索引取key除10取余
s0611163 2021-03-06
  • 打赏
  • 举报
回复
600M不多,好点的服务器,几十个G内存。
橘子皮... 2021-03-06
  • 打赏
  • 举报
回复
引用 38 楼 MuteG 的回复:
可以用List<int>来保存字符串的GetHashCode结果,这个每个字符串的特征码就只占4个字节,1000万条记录,占用空间才几十M。

Dim a As New List(Of String)
        For i = 1 To 10000000
            a.Add(RndName)
        Next
        a.Add("ilovecsdn")

        Dim t As Integer = GetTickCount()
        Dim pd As Boolean = a.Contains("ilovecsdn")
        msgbox(pd.ToString & vbCrLf & (GetTickCount() - t))

Dim a As New List(Of String)
        For i = 1 To 10000000
            a.Add(RndName)
        Next
        a.Add("ilovecsdn".GetHashCode )

        Dim t As Integer = GetTickCount()
        Dim pd As Boolean = a.Contains("ilovecsdn".GetHashCode )
        msgbox(pd.ToString & vbCrLf & (GetTickCount() - t))
为什么我测试的用gethashcode反而慢了一倍的时间??? 前者是47毫秒后者是74毫秒
shijies 2021-03-05
  • 打赏
  • 举报
回复
可以使用嵌入式数据库Berkeley DB保存
wanghan226 2021-03-04
  • 打赏
  • 举报
回复
考虑下用StringBuilder 试试效果
示申○言舌 2021-02-24
  • 打赏
  • 举报
回复
1000万条数据,用List只能遍历查询,效率未必比数据库高。如果真的对数据查询效率要求很高,可以考虑其他数据结构,比如字典(按照URL的MD5值索引),或者自己写一个索引。。想要效率高就得牺牲空间;想要节省空间就要牺牲效率,两者兼得的可能性不大。数据库效率已经很高了,就你这个问题来看,用数据库应该是最好的选择。
MuteG 2021-02-22
  • 打赏
  • 举报
回复
可以用List<int>来保存字符串的GetHashCode结果,这个每个字符串的特征码就只占4个字节,1000万条记录,占用空间才几十M。
zxy2847225301 2021-02-09
  • 打赏
  • 举报
回复
看了你的需求描述,可以使用把字符串(字符串中每个字符转成ascii数字,把数字进行累加,最后加上字符串的长度作为int最终的结果)转换为int类型进行计算(即把List<string>转成List<int>),要比较的网址转成int,最后就能比较了,虽然不能100%保证准确,如果想要更加准确,在第一轮比较相等的情况下,可以进行第二轮算法(自己制定另外一套算法)的比较
shijies 2021-02-09
  • 打赏
  • 举报
回复
以前在一本书里看到解决这个问题用的是hashmap。
  • 打赏
  • 举报
回复
1000万个完全不一样的unicode字符串占这么点儿内存很正常。以每个字符4个字节算,1000万个正好400M。 你有多大内存条?不会是只有4G吧?那最好花2、300块钱换一根8G的内存条,或者添加一根4G内存条。现在配置新的电脑一般都以16G内存为标配。
沫含天下 2021-02-07
  • 打赏
  • 举报
回复
想问一下楼主,都取出来需要对比的是几个字段,单独取出来就行。或者 用下面这个也行,
cuiwei16236 2021-02-07
  • 打赏
  • 举报
回复
同支持redis
加载更多回复(32)

110,537

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧