.net 有没有办法加快读取数据的速度?

.net 有没有办法加快读取数据的速度?,.net,postgresql,sqldatareader,npgsql,data-retrieval,.net,Postgresql,Sqldatareader,Npgsql,Data Retrieval,在程序中,我创建了以下逻辑,用于从数据库读取数据并将其存储到列表中: npgsqlcmd=newnpgsqlcommand(查询,连接); 列表结果=新列表(); Npgsql.NpgsqlDataReader rdr=cmd.ExecuteReader(); while(rdr.Read()) { 字符串userId=rdr[0]。ToString(); 字符串sex=rdr[1]。ToString(); 字符串strDateBirth=rdr[2]。ToString(); 字符串zip=rd

在程序中,我创建了以下逻辑,用于从数据库读取数据并将其存储到列表中:

npgsqlcmd=newnpgsqlcommand(查询,连接);
列表结果=新列表();
Npgsql.NpgsqlDataReader rdr=cmd.ExecuteReader();
while(rdr.Read())
{
字符串userId=rdr[0]。ToString();
字符串sex=rdr[1]。ToString();
字符串strDateBirth=rdr[2]。ToString();
字符串zip=rdr[3].ToString();
UserInfo UserInfo=新UserInfo();
userInfo.Msisdn=userId;
性别=性别;
尝试
{
userInfo.BirthDate=Convert.ToDateTime(strDateBirth);
}
捕获(例外情况除外)
{
}
userInfo.ZipCode=zip;
userInfo.DemographicsKnown=true;
userInfo.AgeGroup=getAgeGroup(strDateBirth);
if(result.Count(x=>x.Id==userId)==0)
结果.添加(userInfo);
}
这段代码的性能非常差。有超过200万条记录,半小时后,列表userInfo只包含30万条记录


有人知道如何加快从数据库读取数据的速度吗?

所有这些执行选项处理都会大大降低程序的速度。异常适用于异常情况如果您的代码抛出的执行次数超过10次,则需要重新考虑您的设计

而不是在每次出现错误的日期时抛出execption。它将大大加快您的代码速度

////Replace This
//try
//{
//    userInfo.BirthDate = Convert.ToDateTime(strDateBirth);
//}
//catch (Exception ex)
//{
//}

//With this
DateTime bithDate;
if(DateTime.TryParse(strDateBirth, out bithDate)
{
    userInfo.BirthDate = bithDate;
}

另外,
rdr[2]
处的列的数据类型是什么?现在已经是约会时间了吗?另一件事是停止对任何地方的对象调用ToString,并使用正确的方法

while(rdr.Read())
{
    UserInfo userInfo = new UserInfo();
    userInfo.Msisdn = rdr.GetString(0);
    userInfo.Gender = rdr.GetString(1);

    DateTime? birthdate = null; //This is a nullable DateTime see http://msdn.microsoft.com/en-us/library/b3h38hb0.aspx

    if(rdr.IsDbNull() == false)
    {
        birthdate = rdr.GetDateTime(2);
        userInfo.BirthDate = birthdate.Value;
    }
    userInfo.ZipCode = rdr.GetString(3);
    userInfo.DemographicsKnown = true;
    userInfo.AgeGroup = getAgeGroup(birthdate); //You may need to edit getAgeGroup to take in a nullable DateTime

    if (result.Any(x => x.Id== userId)) //Any is much faster than count for your check, see Matthew PK's answer.
        result.Add(userInfo);
}

所有这些执行选项处理都大大降低了程序的速度。异常适用于异常情况如果您的代码抛出的执行次数超过10次,则需要重新考虑您的设计

而不是在每次出现错误的日期时抛出execption。它将大大加快您的代码速度

////Replace This
//try
//{
//    userInfo.BirthDate = Convert.ToDateTime(strDateBirth);
//}
//catch (Exception ex)
//{
//}

//With this
DateTime bithDate;
if(DateTime.TryParse(strDateBirth, out bithDate)
{
    userInfo.BirthDate = bithDate;
}

另外,
rdr[2]
处的列的数据类型是什么?现在已经是约会时间了吗?另一件事是停止对任何地方的对象调用ToString,并使用正确的方法

while(rdr.Read())
{
    UserInfo userInfo = new UserInfo();
    userInfo.Msisdn = rdr.GetString(0);
    userInfo.Gender = rdr.GetString(1);

    DateTime? birthdate = null; //This is a nullable DateTime see http://msdn.microsoft.com/en-us/library/b3h38hb0.aspx

    if(rdr.IsDbNull() == false)
    {
        birthdate = rdr.GetDateTime(2);
        userInfo.BirthDate = birthdate.Value;
    }
    userInfo.ZipCode = rdr.GetString(3);
    userInfo.DemographicsKnown = true;
    userInfo.AgeGroup = getAgeGroup(birthdate); //You may need to edit getAgeGroup to take in a nullable DateTime

    if (result.Any(x => x.Id== userId)) //Any is much faster than count for your check, see Matthew PK's answer.
        result.Add(userInfo);
}

当您真正的意思是
.Any()

每当调用
.Count
时,您都在枚举整个集合,以查看是否有一个匹配项

考虑一下你要问的问题:
“您有多少行符合此条件?该数字等于零吗?”

你真正的意思是:
“有符合此条件的行吗?”

在该上下文中,您可以创建一组userId值。在Hashset(或dictionary)中检查是否存在比在列表中检查要快得多

此外,如果您确实已经拥有该用户ID,那么您可以毫无理由地解析并读取所有值。首先检查myHashset.Contains(userId),然后添加

这是它速度慢的主要原因。对于n行,您正在执行集合的第n个三角形枚举

<> > >编辑:考虑未经测试的更改:我不知道你的读者是否支持类型化的读方法,比如<代码> GESTRIGN()/Cuffer >,所以如果它没有,那么简单地使用你以前所拥有的。

NpgsqlCommand cmd = new NpgsqlCommand(query, conn);
List<UserInfo> result = new List<UserInfo>();
Npgsql.NpgsqlDataReader rdr = cmd.ExecuteReader();
HashSet<string> userHash = new HashSet<string>(); // is this actually an int?

while (rdr.Read())
{
    string userId = rdr.GetString(0);
    If (!userHash.Contains(userId))
    {
        string strDateBirth = rdrGetString(2);
        UserInfo userInfo = new UserInfo();
        userInfo.Msisdn = userId;
        userInfo.Gender = rdr.GetString(1);
        datetime parseddate; // this is not used if the parse fails
        if (Datetime.TryParse(strDateBirth, out parseddate))
        {
            userInfo.BirthDate = parseddate;
            // userInfo.AgeGroup = getAgeGroup(strDateBirth); // why take the string?
            // rewrite your getAgeGroup method to take the datetime
            userInfo.AgeGroup = getAgeGroup(parseddate);
        }
        userInfo.ZipCode = rdr.GetString(3);
        userInfo.DemographicsKnown = true;
        result.Add(userInfo);
        userHash.Add(userId);
    }
}
npgsqlcmd=newnpgsqlcommand(查询,连接);
列表结果=新列表();
Npgsql.NpgsqlDataReader rdr=cmd.ExecuteReader();
HashSet userHash=新HashSet();//这实际上是一个int吗?
while(rdr.Read())
{
字符串userId=rdr.GetString(0);
如果(!userHash.Contains(userId))
{
字符串strDateBirth=rdrTargetString(2);
UserInfo UserInfo=新UserInfo();
userInfo.Msisdn=userId;
userInfo.Gender=rdr.GetString(1);
datetime parseddate;//如果解析失败,则不使用此选项
if(Datetime.TryParse(strDateBirth,out parseddate))
{
userInfo.BirthDate=parseddate;
//userInfo.AgeGroup=getAgeGroup(strDateBirth);//为什么要使用字符串?
//重写getAgeGroup方法以获取日期时间
userInfo.AgeGroup=getAgeGroup(parseddate);
}
userInfo.ZipCode=rdr.GetString(3);
userInfo.DemographicsKnown=true;
结果.添加(userInfo);
userHash.Add(userId);
}
}
这将始终保留找到的用户行的第一个实例(当前代码就是这样做的)。如果要保留最后一个实例,则可以使用字典并完全消除
.Contains()
调用


编辑:我刚刚注意到我的示例从未将userId添加到哈希中。。。哎呀。。。在那里添加了它。

您使用的是
.Count
,而您真正的意思是
.Any()

每当调用
.Count
时,您都在枚举整个集合,以查看是否有一个匹配项

考虑一下你要问的问题:
“您有多少行符合此条件?该数字等于零吗?”

你真正的意思是:
“有符合此条件的行吗?”

在该上下文中,您可以创建一组userId值。在Hashset(或dictionary)中检查是否存在比在列表中检查要快得多

此外,如果您确实已经拥有该用户ID,那么您可以毫无理由地解析并读取所有值。首先检查myHashset.Contains(userId),然后添加

这是主要原因