优化未知数据库的查询

时间:2011-09-16 15:48:41

标签: c# sql

第三方应用程序为每个项目创建一个数据库。所有数据库都具有相同的表和结构。可以随时添加新项目,因此我无法使用任何EF模式。

我现在所做的是:

    private IEnumerable<Respondent> getListRespondentWithStatuts(string db)
    {
        return query("select * from " + db + ".dbo.respondent");
    }

    private List<Respondent> query(string sqlQuery)
    {
        using (var sqlConx = new SqlConnection(Settings.Default.ConnectionString))
        {
            sqlConx.Open();
            var cmd = new SqlCommand(sqlQuery, sqlConx);
            return transformReaderIntoRespondentList(cmd.ExecuteReader());
        }
    }

    private List<Respondent> transformReaderIntoRespondentList(SqlDataReader sqlDataReader)
    {
        var listeDesRépondants = new List<Respondent>();

        while (sqlDataReader.Read())
        {
            var respondent = new Respondent
            {
                CodeRépondant = (string)sqlDataReader["ResRespondent"],
                IsActive = (bool?)sqlDataReader["ResActive"],
                CodeRésultat = (string)sqlDataReader["ResCodeResult"],
                Téléphone = (string)sqlDataReader["Resphone"],
                IsUnContactFinal = (bool?)sqlDataReader["ResCompleted"]
            };

            listeDesRépondants.Add(respondent);
        }

        return listeDesRépondants;
    }

这样可以正常工作,但速度非常慢(每分钟20 000条记录)。你对什么策略应该更快有任何暗示吗?对于信息,真正慢的是transformReaderIntoRespondentList方法

谢谢!

1 个答案:

答案 0 :(得分:2)

一般来说,任何SELECT * FROM都是不好的做法,但也可能导致您需要撤回比实际需要更多的数据。转换只在几列上运行,列数多于返回所需的列数?考虑替换为:

  private IEnumerable<Respondent> getListRespondentWithStatuts(string db)
  {
    return query("select ResRespondent, ResActive, ResCodeResult, Resphone, ResCompleted  from " + db + ".dbo.respondent");
  }

此外,反对SQL注入攻击;查询SQL查询的字符串非常危险。

从DataReader中提取数据时,我发现使用非命名查找效果最佳:

  var respondent = new Respondent
  {
    CodeRépondant = sqlDataReader.GetString(0),
    IsActive = sqlDataReader.IsDBNull(1) ? (Boolean?)null : sqlDataReader.GetBoolean(1),
    CodeRésultat = sqlDataReader.GetString(2),
    Téléphone = sqlDataReader.GetString(3),
    IsUnContactFinal = sqlDataReader.IsDBNull(4) ? (Boolean?)null : sqlDataReader.GetBoolean(4)
  };

我很久没有对性能差异进行过充分的测试;但这曾经产生了显着的差异。序数检查不必进行命名查找,也避免装箱/取消装箱值。

除此之外,没有更多信息,很难说......你需要所有20,000条记录吗?

<强>更新

使用300,000条记录进行简单的本地测试用例,并将所有数据的加载时间缩短近50%。我想这些结果会根据检索的数据类型而有所不同;但它仍然会对整体执行时间产生影响。话虽如此,在我的环境中,我们正在谈论从650毫秒到超过300毫秒的下降。

注意

如果respondent是一个视图,那么可能“非常慢”的是建立结果集的数据库;虽然数据读取器将在记录可用时立即开始处理信息,但最终的瓶颈将是数据库本身和/或网络延迟。除了上述优化之外,除非您可以索引视图/表以优化查询和/或减少所需信息,否则您无法对代码执行任何操作。