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

求高手的一个解决方案!

    现在我手里有竟将20W的会员数据,因为很多会员都留有留的有QQ ! 因为腾讯已经给出了验证QQ是否在线的客服代码! 我现在想很快的区分开那些会员在线状态! 
   本来想先判断会员是否在线状态,更新数据库后在放入条件查询,但是20w的数据更新状态太耗时了!  
  求大神们给个解决方案! --------------------编程问答-------------------- 没说清楚更新的策略。数据库刷20万的数据还是很快的。 --------------------编程问答--------------------   目标很明确,更具会员的QQ信息,筛选查询实时在线的会员里列表! --------------------编程问答--------------------
引用 1 楼 guwei4037 的回复:
没说清楚更新的策略。数据库刷20万的数据还是很快的。

    由于每一个会员是否在线的状态都要通过在线客户的代码验证,所以我刚开始的思路需要更新到每一条数据! 
这样效率值得怀疑!
--------------------编程问答-------------------- 逐条判断肯定是要的了
更新的时候 采用事务提交
可以每500条或更多在线状态的数据
commit一次 --------------------编程问答--------------------
引用 4 楼 u011096386 的回复:
逐条判断肯定是要的了
更新的时候 采用事务提交
可以每500条或更多在线状态的数据
commit一次

  楼上的意思是,展示数据列表之前,先吧会员的数据遍历一次,修改当前QQ的在线状态! 然后再更具条件条件查询?   --------------------编程问答--------------------
引用 5 楼 woshilaihua 的回复:
Quote: 引用 4 楼 u011096386 的回复:

逐条判断肯定是要的了
更新的时候 采用事务提交
可以每500条或更多在线状态的数据
commit一次

  楼上的意思是,展示数据列表之前,先吧会员的数据遍历一次,修改当前QQ的在线状态! 然后再更具条件条件查询?  


只是在展示数据时  将会员qq是否在线状态显示?
这样 qq是有用脚本判断是否在线的方式
--------------------编程问答-------------------- QQ系在客户代码,src返回的是不同图片!src="http://wpa.qq.com/pa?p=1:<%# Eval("QQ") %>:4" --------------------编程问答-------------------- 那又怎么样呢? 你难道用别的就不用去便利20W的数据量了? 效率高 存储过程呗 骚年 --------------------编程问答-------------------- 可以批量的处理。比如5000条5000条的。记得带事务哦。 --------------------编程问答-------------------- 前几天在论坛上看到一个可以用存储过程调用webservice的,我觉得你可以一试。利用webservice可以判断是否在线,这很容易做到,再配合存储过程的调用,再加上事务的处理。应该不难。 --------------------编程问答--------------------
引用 楼主 woshilaihua 的回复:
    现在我手里有竟将20W的会员数据,因为很多会员都留有留的有QQ ! 因为腾讯已经给出了验证QQ是否在线的客服代码! 我现在想很快的区分开那些会员在线状态! 
   本来想先判断会员是否在线状态,更新数据库后在放入条件查询,但是20w的数据更新状态太耗时了!  
  求大神们给个解决方案!


仅凭你的这个“空想出来”的需求,我看不到它的意义。假设说腾讯api给出的状态可以反映最近30秒钟内的情况,那么你是打算每隔30秒钟轮询一遍20W人的状态么?如果不轮询,你又怎么知道30秒钟之后哪些人的状态改变了呢?

有些人满脑筋只有数据库表“增删改查”,没有协同服务的设计概念。

如果你是做一个实用的交互操作软件,那么需要显示用户在线状态时才会调用一下api。有什么必要保存到数据库里?凭空出来的“设计流程”,其白白浪费的时间是可怕的。 --------------------编程问答--------------------
引用 2 楼 woshilaihua 的回复:
  目标很明确,更具会员的QQ信息,筛选查询实时在线的会员里列表!


应该结合实际去指定目标。你需要稍微深入一点才能搞清楚流程设计(又没有速度和价值保证)的时候,一定不要停留在标题党方式的设计上。 --------------------编程问答-------------------- 才能搞清楚流程设计(又没有速度和价值保证)的时候  -->  才能搞清楚流程设计(有没有速度和价值保证)的时候

所以许多设计,首先需要你实际调查研究数据的来源和使用流程。而绝不是拿着静态的数据库表就空想自己的操作。 --------------------编程问答-------------------- 数据库无论是查询、插入、更新20万条数据都几乎不耗时,耗时的部分主要在查询那个qq在线状态。我用的是http://webpresence.qq.com/getonline?Type=1&这个页面,每次可以同时查询5个QQ号码。使用.net4.0的TPL并行运算的话20万条数据约莫要20分钟左右。
当然了,如果你能直接查询腾讯的数据库的话,一次取20万条数据依然会很快。
问题出在每次最多取5个,我试了下,一般一次连接检查5个QQ的状态的话约莫要0.065秒,20万条数据要4万次连接至少要43分钟才行。
所以我有以下几个建议:
1、QQ状态不需要存入数据库。这是因为在线状态都是实时更新的,即使存入数据库,你要取出来还是要连接腾讯网络判断下,实在没什么必要。当然了,数据库根本不算是个问题,20万条数据无论如何增删改也不会占去20-40分钟。
2、不提供显示当前在线总人数的查询控件。虽然我不知道你的UI是什么样子的,但是无论是谁都不会一眼去看20万个QQ的在线状态。唯一有关的可能就是会有一个控件显示当前在线的总人数,由于更新时间过长,建议此功能取消。
3、分页显示在线QQ号码,每次只显示一部分。或者也可以让用户选择将某些重要的QQ号码加入优先级,每次优先读取这些号码的在线状态。也可以选定号码的查询范围,总之尽可能地使每次查询的时间缩短在2秒内,2/0.065大约为30条数据。

下面我贴一下我写的测试用代码,如果你有什么问题的话敬请联系。

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace QqStatusQuery
{
    internal class Program
    {
        private static Dictionary<int, bool> dictionary = new Dictionary<int, bool>();
        private const char colon = ':';
        private static int idCount;

        public static void Main(string[] args)
        {
            Console.WriteLine("QQ状态检查程序");

            for (int i = 200000; i < 400000; i++)
            {
                dictionary.Add(i, false);
            }

            Console.WriteLine("数据读取完毕");

            var list = new List<QqId>() { new QqId() };
            int count = 0;

            foreach (var id in dictionary.Keys)
            {
                if (!list[count].IsFull)
                {
                    list[count].Add(id);
                }
                else
                {
                    list.Add(new QqId());
                    count++;
                }
            }

            Console.WriteLine("开始检查状态");
            var startTime = DateTime.Now;
            idCount = list.Count;

            Parallel.ForEach<QqId>(list, id => CheckStatus(id));

            Console.WriteLine("一共耗时" + (DateTime.Now - startTime).TotalSeconds.ToString());
            //Console.WriteLine("以下为登录状态");

            //foreach (var key in dictionary.Keys)
            //{
            //    if (dictionary[key])
            //    {
            //        Console.WriteLine(key);
            //    }
            //}

            Console.Read();
        }

        private static void CheckStatus(QqId id)
        {
            var html = GetWebResponse(BuildString(@"http://webpresence.qq.com/getonline?Type=1&", id[0], colon, id[1], colon, id[2], colon, id[3], colon, id[4], colon));

            var splitedString = html.Split(';');

            for (int i = 0; i < splitedString.Length; i++)
            {
                var status = splitedString[i];

                if (!string.IsNullOrEmpty(status) && status[status.Length - 1] == '1')
                {
                    dictionary[id[i]] = true;
                }
            }
        }

        private static string GetWebResponse(string url)
        {
            string html = string.Empty;

            try
            {
                var request = WebRequest.Create(url);
                var response = request.GetResponse();
                var stream = response.GetResponseStream();
                var encoding = Encoding.GetEncoding("GBK");
                var reader = new StreamReader(stream, encoding);
                var readbuffer = new char[short.MaxValue];
                var n = reader.Read(readbuffer, 0, short.MaxValue);

                while (n > 0)
                {
                    html = BuildString(html, new string(readbuffer, 0, n));
                    n = reader.Read(readbuffer, 0, short.MaxValue);
                }
            }
            catch (WebException)
            {
            }

            return html;
        }

        private static string BuildString(params object[] inputStrings)
        {
            var builder = new StringBuilder();

            foreach (var inputString in inputStrings)
            {
                if (inputString != null)
                {
                    builder.Append(inputString.ToString());
                }
            }

            return builder.ToString();
        }
    }

    internal class QqId
    {
        private int[] Ids;
        private byte count;

        internal QqId()
        {
            Ids = new int[5];
        }

        internal int this[int index]
        {
            get
            {
                return Ids[index];
            }
        }

        internal bool IsFull
        {
            get
            {
                return count == 5;
            }
        }

        internal void Add(int id)
        {
            Ids[count++] = id;
        }
    }
}
--------------------编程问答-------------------- 学习。。。。。
补充:.NET技术 ,  ASP.NET
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,