Оптимизировать запрос по неизвестной базе данных - PullRequest
1 голос
/ 16 сентября 2011

Стороннее приложение создает одну базу данных для каждого проекта.Все базы данных имеют одинаковые таблицы и структуру.Новые проекты могут быть добавлены в любое время, поэтому я не могу использовать какую-либо схему 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 Ответ

2 голосов
/ 16 сентября 2011

Вообще говоря, что-либо SELECT * FROM - это плохая практика, но это также может привести к тому, что вам придется отозвать больше данных, чем фактически требуется. Преобразование работает только на несколько столбцов, возвращено ли больше столбцов, чем требуется? Попробуйте заменить на:

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

Также gaurd против атак 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 записей?

UPDATE

Запустил простой локальный тестовый пример с 300 000 записей и сократил время загрузки всех данных почти на 50%. Я полагаю, что эти результаты будут различаться в зависимости от типа данных, которые будут получены; но это по-прежнему имеет значение для общего времени выполнения. При этом в моем окружении мы говорим о снижении с 650 мс до чуть более 300 мс.

Примечание

Если respondent является представлением, то, что, вероятно, "действительно медленно", это база данных, создающая набор результатов; хотя считыватель данных начнет обрабатывать информацию, как только появятся записи, основным узким местом будет сама база данных и / или задержка в сети. Помимо приведенных выше оптимизаций, вы вряд ли сможете сделать что-то с вашим кодом, если только вы не можете проиндексировать представление / таблицу для оптимизации запроса или уменьшения требуемой информации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...