读书人

Listlt;Tgt; 内存储器中大数据量查询优化

发布时间: 2013-01-18 10:22:42 作者: rapoo

List<T> 内存中大数据量查询优化
List<T> 中数据我存了3千万条数据,内存用了一个G左右,查询数据基本上用时在1.5 秒左右,想要优化,请问各位有没有什么好的建议?(不用数据库是因为这个数据变化不大,而且使用特别频繁,更重要的是数据库估计也抗不住)
[解决办法]
你需要的是词法分析,索引与方向索引。
[解决办法]

引用:
楼主需要的是算法,比如trie

如果对自己写算法没把握,或者要求不高的话,可以考虑开源的lucene.net
[解决办法]
试试 lucene 。 你的效果,要做分词, 索引 。 效率才能上去
[解决办法]
查询优化,主要是要做好索引。
比如,针对每个记录都比较短(<100),内存充裕的情况,可以对所有的字进行索引(常用汉字,可能就几千个)。
如果你知道包含'高'的字符串在[123,56789]等记录,那么匹配'高手'的时候,你只要到这些记录里面去搜索。
甚至你可以把包含'高','手'的记录作并集后,再进行匹配。

000001: 你好
...
000123: 高手
...
056789: 我是高手
...

---- 单字索引 ----
[00065]A:
[20320]你: 1
[22909]好: 1
[39640]高: 123, 56789


[解决办法]
就丢在数据库里吗建好索引就ok了

数据库索引本来就是一个hash表分布,可以快速定位。


[解决办法]
这个本来应该是由数据库完成的功能,何必自己去造轮子呢.由一些内存数据可供选择.

[解决办法]
你这LIST查询怎么写的啊 是for循环还是FindAll
lis1 = lis.FindAll(sk1 => sk1.Key.Contains("高"));
这一种看看
[解决办法]
Task多线程查询,应该会好点
[解决办法]
建个索引就好,比如下边这样。如果你不想包装IList的n多方法也可以直接从List<T>继承,但基本的Add Remove还是要重写成同步维护索引的


public class ListWithIndex<PrimaryKeyType, DataType> : IList<DataType>
{
List<DataType> data;
Dictionary<PrimaryKeyType, DataType> index;

public DataType this[int index]
{
get
{
return data[index];
}
set
{
data[index] = value;
}
}

public DataType this[PrimaryKeyType index]
{
get
{
return this.index[index];
}


set
{
this.index[index] = value;
}
}
}


[解决办法]
对解决办法有兴趣
[解决办法]

[解决办法]


[解决办法]
关注LZ最终如何解决的,希望LZ给点分,好通知。谢谢。
[解决办法]
关注中,工作也遇到类似的问题,我们的数据大概几百万条,但列比较多,放到datatable 直接内存溢出(32位),后来移掉一些数据 才能正常使用,程序改成64位,内存会支持更大, 但这样也不是很好的解决方法 不知道大家怎么处理这种大数据量的问题的
[解决办法]
引用:
引用:3千万条数据,都放到内存中? 真牛!
内存那么宝贵的资源,就这样被你废掉了。还带来一堆的问题。

现在的内存是最便宜的
服务器的内存能达到几十G
3千万条数据也不过2G吧
但内存的速度比数据库,比硬盘快多了
做服务端开发的,都是把数据扔内存里
不可能直接查数据库的


水 一吨 也才几块钱,就可以用来 浪费么?
[解决办法]
再说了,一旦程序重新启动了。 要往内存中重新装载这 3千万 条的数据,就不花费时间么!
万一当时,你的内存不够了,你又怎么办?

要我说的话,做这样的事情简直愚蠢至极!!!!!!!!!!!!!!!!!!!
[解决办法]
引用:
引用:3千万条数据,都放到内存中? 真牛!
内存那么宝贵的资源,就这样被你废掉了。还带来一堆的问题。

放数据库,用数据库的话,定一个like语句,18秒,18秒啊。。。。。
我愿意那客户不愿意啊。


like只有关键字开头的索引才有用,大多数时候还是全表扫描,跟遍历是一样的道理(Linq查询,一样是要遍历),所以最后放在内存里面肯定要快些
不知LZ有没有用上多线程,话说现在的服务器CPU爆强,把三千万的查询分化为若干个查询,
Net4.0+可直接用AsParallel()
[解决办法]
开多少个线程合适,你可以多做些测试,注意监视CPU的占用,尽量让其上去
[解决办法]
引用:
再说了,一旦程序重新启动了。 要往内存中重新装载这 3千万 条的数据,就不花费时间么!
万一当时,你的内存不够了,你又怎么办?

要我说的话,做这样的事情简直愚蠢至极!!!!!!!!!!!!!!!!!!!

哥们说的这话,我是万分赞同。艰苦朴素是伟大传统,怎么能这么践踏呢?再说了,内存放那里又不会坏掉,应该留着以后用。
我倒是想到一个方案,不怎么消耗内存,而且反应速度接近于0.1s(虽然比0.00xxx ms差的有点远,但是至少比楼主的效率高)。
比如,我们可以请3KW个人,每个人强化训练一条数据(据说人的反应速度接近于0.1s),所有人都监视着用户的输入,并且条件反射按下匹配按钮。
[解决办法]
使用lucene全文检索吧,肯定在1秒内响应

[解决办法]
http://msdn.microsoft.com/zh-tw/magazine/cc163329.aspx

并行查询。
[解决办法]


3、当用户输入“糕”时,先查Word_Index表,得到记录id结果集,再用id在词汇List中找到对应的词组。
List<T> 内存储器中大数据量查询优化
4、当用户输入“糕富”时,在Word_Index表查“糕”和“富”对应的ID1、ID2记录集,并满足ID1=ID2,将共同拥有的ID集合在词汇List中找到对应词组。
备注:如果这样做,当然,以前的3000w数据得私下把索引建好。以后每次新加词组时及时更新Word_Index表。
[解决办法]
用内存好吧,这样不用频繁的查询数据库
[解决办法]
引用:
不知道楼主的问题解决没有。我有一个思路。
1、首先建立一个常用汉字表(假设表名为Word_Index),也就几千来个。这个可以存到数据库里面,毕竟数据量小。
2、每次新增数据时,将字符串中对应的ID值加到Word_Index对应的记录。
如图所示:

3、当用户输入“糕”时,先查Word_Index表,得到记录id结果集,再用id在词汇List中找到对应的词组。……


好方法

[解决办法]
用list_entry,不管list有多少数据,一次查询就可以了。

#define list_entry(ptr, type, member) \
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))


不熟悉的可google一下。

这也是c/c++速度快的原因。


[解决办法]
可以考虑使用NoSql试试。
你的数据结构比较简单,受用noSQL肯定能应付的了。再说你放到内存只能解决当前的问题。将来数据更大怎么办?
搜索引擎处理大数据的时候肯定用到了索引。你把常用的词语建立索引后在搜索,肯定快多了!
[解决办法]
如果你学过数据结构可能知道,比如对于1000万数据,假设已经排序,进行二分查找其花费的时间相当于要比较2000个数据;而假设没有排序,那么进行遍历查找则相当于要比较500万数据。

在大数据量面前,这2500倍的差距,不关心它的人一定是不懂数据结构,而不是“花得起”这个时间。

因此说到“索引、排序”(如果你的查询需要用到多个次序,当然就需要另外在内存里建立索引结构)肯定是对的!你不要把这个理解为什么“重新把数据扔回关系数据库里”。就算是内存处理,也可以索引啊!

最后,如果你想省事,那么使用一种“内存数据库”,因为它提供数据库知识(特别是在内存里索引、支持各种查询sql等),而不要自己去管理什么“3千万数据”了!
[解决办法]
你的sql语句用个索引,建个索引会比较好一下,因为大量的数据查询,建个索引是比较好的。还有其他的方法。
[解决办法]
刚去看了,,,百度和 google 的下拉提示条。。。都是根据第一个汉字给的提示。。。


2:用模糊查询字符串。如用户输入"高",给提示“高手”,“我是高手”,“我很高”。有点儿像百度的下拉提示一样。


提示数据库都是,亿,千万 级别的。。用户输入“高”。根据第一个字符给提示的就已经够多呢,,根本不需要 给出 我是高手,我很高这2个提示。。。。



这个应该优化的是。。查询频率。。。比如 用户输入“高” 应该给出的 以“高” 开头 使用频率比较高的词。。。


这个用 List 不是很好实现,,,不过用 数据库就比较好实现呢。。。


用户查询后,,可以在数据库里面+1


总之用数据库比用 List好处不止多一点,,,可以做查询统计,关键字屏蔽等等功能。


tab_long ;里面存放所用拼音 long 开头的词组
tab_gao ;里面存放所用拼音 gao 开头的词组
tab_a
tab_b
tab_c
tab_d

[解决办法]

 


[解决办法]
List<T> 内存储器中大数据量查询优化
我用了20000000数据试了试
效果如图
[解决办法]
并行linq看看....
类似这个
var q1 = (from x in Partitioner.Create(data).AsParallel()
where x < 80
select x).Sum();
[解决办法]

 List<string> Data = new List<string>();

string Randomstr = "功夫撒黑胡椒hcbvf蜂窝qwertyuiopasdfghjklzxcvbnm法国的恢复到飞范德萨QWERTYUIOPASDFGHJKLZXCVBNM出现过热423贴①46546也有一头热刚恢复到贴3天赋如头3广泛的我让他";


Random rd = new Random(GetRandomSeed());

static int GetRandomSeed()
{
byte[] bytes = new byte[4];
System.Security.Cryptography.RNGCryptoServiceProvider rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
rng.GetBytes(bytes);
return BitConverter.ToInt32(bytes, 0);
}
public Form1()
{
InitializeComponent();


for (int i = 0; i < 20000000; i++)
{
Data.Add(Randomstr.ToCharArray()[rd.Next(Randomstr.Length)].ToString()
+ Randomstr.ToCharArray()[rd.Next(Randomstr.Length)].ToString()
+ Randomstr.ToCharArray()[rd.Next(Randomstr.Length)].ToString()
+ Randomstr.ToCharArray()[rd.Next(Randomstr.Length)].ToString()
+ Randomstr.ToCharArray()[rd.Next(Randomstr.Length)].ToString());
}

this.textBox1.AutoCompleteCustomSource.Clear();
this.textBox1.AutoCompleteCustomSource.AddRange(Data.ToArray());
this.textBox1.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend;
this.textBox1.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.CustomSource;


}



List<T> 内存储器中大数据量查询优化
求采纳

[解决办法]
像楼上说的也没什么别的好办法,两个思路,通过索引查,或者是分段开多线程同时查。
如果如你所说内存不成问题,最简单的方法,就是按你的机器配置,比如:开5个线程同时查,每个线程遍历600万数据。
[解决办法]
建议你用 TRS SERVER ,百度 TRS SERVER
[解决办法]

[解决办法]
内存数据库,我们的项目一直再用,可惜的是我还没有接触这个方面的,我接触的还是在线数据库操作。
[解决办法]
我很想知道.楼主的3千万数据是如何存放内存的.内存只是一个暂存.服务器重启后内存就会丢失,哪你3千万的数据不就丢失了....List<T> 内存储器中大数据量查询优化
[解决办法]
3千万条数据 1.5秒??
已经相当不错,
只占1g内存 说明key里,字符不是太长。
[解决办法]
1:数据特征就 一个ID,一个字符串,字符串长短肯定是不一样长度的。数据结构相对来说还是比较简单的.
这个适合用哈希O(1),或者List有序,做折半查找O(LgN)。

2:用模糊查询字符串。如用户输入"高",给提示“高手”,“我是高手”,“我很高”。有点儿像百度的下拉提示一样。

这个适合用倒排索引。每两个字做一个Key

总之,你这些数据,如果想追求极限速度:

1,原始数据做哈希索引。
2,针对不同查询,要做不同的“列存储”,值就是ID的集合,hashset就可以。
3,等于的查找用哈希,范围查找用二叉或者有序。

你本人需要改造,需要有复杂度评估的意识,你要知道我说的O(1),O(LgN)是什么意思。
你看微软的MSDN上对各种结构体的增删查改都有复杂度的评估,大欧记法神马的最关键了。

学会评估复杂度,不做“伪程序员”!

读书人网 >C#

热点推荐