当前位置:编程学习 > C#/ASP.NET >>

ExecuteReader()占用CPU严重的问题,请高手们帮助!


由于项目需要对数据库频繁查询,所以做了个测试,发现DataBaseCommad.ExecuteReader()占用CPU非常严重。
但是我朋友的VC程序这样做却没问题,CPU占用一直是0很稳定。请问这里的高手们有什么好的方法在C#中解决这个问题。
我做过的尝试:用datatable做内存表,此方式可以解决CPU占用问题,并可提高查询速度,但会占用很大存,不可行。
高手们还有没有其它方法。用C#程序代码最好,实在不行,用C#调用外部代码也可以,请给个例子。

private void test1()
        {
            while (true)
            {
                lock (thisLock)
                {
                    ++testThreadID;
                    string sql = "select * from test where filed0='" + testThreadID + "'";
                    DataBaseCommad.CommandText = sql;
                    DataBaseResult = DataBaseCommad.ExecuteReader(CommandBehavior.SingleRow);
                    if (DataBaseResult.Read())
                        Console.WriteLine("test1输出: {0}{1}", DataBaseResult["filed0"], DataBaseResult["filed1"]);
                    else
                        Console.WriteLine("test1输出: {0}{1}", testThreadID, "没有找到");
                    DataBaseResult.Close();
                }
                Thread.Sleep(1);
            }
        } --------------------编程问答-------------------- 数据库频繁查询或数据库量大时对CPU或内存的占用不可避免,牺牲点内存把部分数据放缓存里应该可以。
关注中…… --------------------编程问答--------------------
引用 1 楼 wangliangliang 的回复:
数据库频繁查询或数据库量大时对CPU或内存的占用不可避免,牺牲点内存把部分数据放缓存里应该可以。
关注中……

谢谢你的回复!
此方式不适用我的项目,数据查询量是很大的,会不断的接收到查询请求,且数据表也很大。所以不适合
做成内存表的形式。
--------------------编程问答-------------------- 数据量是不是很大,或者你sleep();搞大一点 --------------------编程问答-------------------- 这和 ExecuteReader 有啥关系,while(true) 不断查询,你把 ExecuteReader 注释掉也是CPU占用100%

while(true)
{
    Thread.Sleep(1); //这里改为 Sleep(500) 能把cpu使用率降下来。
}

--------------------编程问答--------------------
引用 4 楼 fangxinggood 的回复:
这和 ExecuteReader 有啥关系,while(true) 不断查询,你把 ExecuteReader 注释掉也是CPU占用100%

C# code

while(true)
{
    Thread.Sleep(1); //这里改为 Sleep(500) 能把cpu使用率降下来。
}


你们误解了,我这个项目就是要求实时性很高的,所以Thread.Sleep(1); 是一种极限测试方式。
我说ExecuteReader 有问题,是因为性能分析器定位性能瓶颈是这里,经过测试也确实是ExecuteReader 
在占用CPU,而不是其它。
朋友用VC实现同样测试的效果却是,CPU占用一直为0很稳定,现在我的整个项目的性能瓶颈就是这个地方了
,所以要找到解决或替换ExecuteReader 的方法。
--------------------编程问答-------------------- 顶机器人


尽量用上缓存吧,除非数据的更新频率更在查询频率之上 --------------------编程问答-------------------- VC CPU占用为0。。。这个不可信。(编译器优化的另说) 
执行代码都是要耗CPU的。该不会是VC那边用多核CPU,你这只有单核吧。

--------------------编程问答-------------------- Reader()是独占数据库连接并且一直保持连接的,且每次只向前读取一行
数据表很大?大到什么程序呢 --------------------编程问答--------------------
引用 6 楼 dongxinxi 的回复:
顶机器人


尽量用上缓存吧,除非数据的更新频率更在查询频率之上

能否说详细点,我在这里用到的数据是没有更新的,只有查询。
缓存怎么用?不要DATASET
--------------------编程问答-------------------- 另外1ms间隔的频繁查询有没有意义呢?数据写入,UI显示可能都不止1ms。 --------------------编程问答--------------------
引用 7 楼 fangxinggood 的回复:
VC CPU占用为0。。。这个不可信。(编译器优化的另说) 
执行代码都是要耗CPU的。该不会是VC那边用多核CPU,你这只有单核吧。

机器配置相同,如果VC编译器能优化到这个程度,那么C#能有什么方法达到VC的境界(只针对本帖讨论内容) --------------------编程问答-------------------- 不管你的数据表大多大,你上面的程序循环一次只读取一行
你完全可以一次将某个ID范围内的数据通过一个Reader来读,这样就不会频繁的执行下面这几行
string sql = "select * from test where filed0='" + testThreadID + "'";
DataBaseCommad.CommandText = sql;
DataBaseResult = DataBaseCommad.ExecuteReader
而只需要前读while(DataBaseResult.Read()) --------------------编程问答-------------------- 你上面那种搞法搞不好甚至都有可能把数据库连接池耗干了,因为1毫秒,有些资源甚至都来不及回收 --------------------编程问答--------------------
引用 8 楼 dongxinxi 的回复:
Reader()是独占数据库连接并且一直保持连接的,且每次只向前读取一行
数据表很大?大到什么程序呢


其实数据库也不是很大,只有80兆而已,只是表多点,每个表有8000左右条记录。
但是问题不是出在数据库的,你可以试一下,访问一个只有一个表,一条记录的数据库。效果是一样的
--------------------编程问答--------------------
引用 13 楼 dongxinxi 的回复:
你上面那种搞法搞不好甚至都有可能把数据库连接池耗干了,因为1毫秒,有些资源甚至都来不及回收

连接是一直开的,直到本实例结束才关闭连接的。这个不是网页程序,是WINFORM程序。 --------------------编程问答-------------------- DataBaseCommad.ExecuteReader这个只需要执行一次就可以了啊,执行查询要传输SQL,数据库那边还要编译查询访IO读数据,像你上面那样搞,每次循环都要这么搞一遍(虽然数据库对SQL也有缓存)
--------------------编程问答--------------------
引用 12 楼 dongxinxi 的回复:
不管你的数据表大多大,你上面的程序循环一次只读取一行
你完全可以一次将某个ID范围内的数据通过一个Reader来读,这样就不会频繁的执行下面这几行
string sql = "select * from test where filed0='" + testThreadID + "'";
DataBaseCommad.CommandText = sql;
DataBaseResult = ……


可能我没说清楚,我这个项目是要求实时查询,是根据接收到的一个请求查询出对应的一条数据进行反馈 --------------------编程问答-------------------- 你上面说了,你的数据不涉及更新,并且只有8000条,你一次全读进来(DataTable),后面的查询直接就可以通过主键在内存表中找是很快的,并且也不需要再跑数据里面查询,但不知道为什么你不要用这种

8000条数据真是小CASE --------------------编程问答--------------------
引用 16 楼 dongxinxi 的回复:
DataBaseCommad.ExecuteReader这个只需要执行一次就可以了啊,执行查询要传输SQL,数据库那边还要编译查询访IO读数据,像你上面那样搞,每次循环都要这么搞一遍(虽然数据库对SQL也有缓存)

如果只执行一次,那么我在接收到下一个请求时,怎么能正确得到数据库的对应记录进行反馈呢? --------------------编程问答--------------------
引用 18 楼 dongxinxi 的回复:
你上面说了,你的数据不涉及更新,并且只有8000条,你一次全读进来(DataTable),后面的查询直接就可以通过主键在内存表中找是很快的,并且也不需要再跑数据里面查询,但不知道为什么你不要用这种

8000条数据真是小CASE

内在占用太多了啊,哥哥!我还说了,有很多表的。50个表左右。 --------------------编程问答--------------------
引用 18 楼 dongxinxi 的回复:
你上面说了,你的数据不涉及更新,并且只有8000条,你一次全读进来(DataTable),后面的查询直接就可以通过主键在内存表中找是很快的,并且也不需要再跑数据里面查询,但不知道为什么你不要用这种

8000条数据真是小CASE

C#程序本来就很占内存,再把所有表加入存中缓存,那内存占用就太吓人了,8000条数据是不多,可是记录中
有的字段数据很大的,一个表都可能是10M(有的表可能还要大些)那50个表内存占多大?还让不让人活了。
此方式我是试过了的,效率和性能是高,可是空间换时间,换得有点不值啊。 --------------------编程问答-------------------- 那么也可以分区间查吧,比如一次查100条,然后递增
或者你根据实测再相应的调整一下,又要少用内存,又要保证效率只能慢慢优化了 --------------------编程问答--------------------
引用 22 楼 dongxinxi 的回复:
那么也可以分区间查吧,比如一次查100条,然后递增
或者你根据实测再相应的调整一下,又要少用内存,又要保证效率只能慢慢优化了

很感谢你这么热心的帮我想办法!分区间查也不行的,我给出的代码是压力测试性能的。实际应用时,是来一个请求就根据请求ID返回一条对应记录,只需一条记录返回就够了,所以分区间的方式行不通的。 --------------------编程问答-------------------- 以前C#一直慢得要死,到2008后终于快起来了,现在winform程序性能也可以了,我把代码也尽量优化了。本想现在C#程序终于能接尽实时要求高的应用了,没想到在这里遇上了瓶颈,真郁闷啊,我已经三天没睡好了,为了找这个瓶颈,每天都是4,5点才睡,10点左右就起床,到处找资料,就是没有找到解决办法,只好来这里发帖求助,难道就没有人遇到我这样的问题了么? --------------------编程问答-------------------- 抱歉,我看以你上面的++ID 如果ID是连接的,一次将100条查出来,后面99条都可以直接在内存表中查询,这样可以尽量减少往返数据库以及读IO的次数

如果查询的目标数据完全没有任何规律,也只能一条一条查询了,缓存就是传说中的Cache了 --------------------编程问答--------------------
引用 25 楼 dongxinxi 的回复:
抱歉,我看以你上面的++ID 如果ID是连接的,一次将100条查出来,后面99条都可以直接在内存表中查询,这样可以尽量减少往返数据库以及读IO的次数

如果查询的目标数据完全没有任何规律,也只能一条一条查询了,缓存就是传说中的Cache了

再次谢谢你的热心解答与讨论!Cache方式怎么用,能给个例子吗 --------------------编程问答-------------------- 使用数据库的应用,1ms查一次真是没什么必要。你可能需要从设计上重新考虑。

另外,如果你说的VC真的那么无压力,你完全可以调用C++封装的dll --------------------编程问答-------------------- 楼主这个程序CPU不应该是这种结果。
楼主可以查一下,是不是有多个实例同时在跑这个while --------------------编程问答--------------------
引用楼主 luobo800 的回复:
由于项目需要对数据库频繁查询,所以做了个测试,发现DataBaseCommad.ExecuteReader()占用CPU非常严重。
但是我朋友的VC程序这样做却没问题,CPU占用一直是0很稳定。


那你就把自己的程序删掉,调用用他的那部分程序好了。 --------------------编程问答--------------------
引用 11 楼 luobo800 的回复:
机器配置相同,如果VC编译器能优化到这个程度,那么C#能有什么方法达到VC的境界(只针对本帖讨论内容)


你都不贴出VC程序,这个“境界”只能人云亦云啦。既然你认为VC程序是一种境界,那么你首先测试VC程序是真正可以测试通过的(例如数据库中的数据被使用查询分析器来大量修改时其输出也是最新数据而不是垃圾数据),然后贴出你的VC程序,这样才好问别人那个程序是什么境界啊。 --------------------编程问答-------------------- 代码有问题 啊。循环套错了 --------------------编程问答-------------------- 80M全缓存到内存里又能有多大负担呢?
8000条数据就更不是事了,以前做个系统,省市县乡四级行政数据有45xxx条,因为查询量相当大,所以全读到内存里面,除了启动的时候慢一些以外,在PC上跑都不觉得有什么影响。
补充:.NET技术 ,  C#
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,