Dapper Multiple Query Читать медленно - PullRequest
0 голосов
/ 25 октября 2018

Я видел много вопросов по этому поводу и объяснения Марка Гравелла, почему он не хочет продолжать играть с множественной сеткой на dapper.

Но я просто хочу кое-что понять

var grid = context.QueryMultiple(string.Join(" ; ", selectCommands));
return queries.Select(q => grid.Read<T>()).AsList();

В этом случае QueryMultiple выполняется около 3 секунд (что в значительной степени соответствует времени выполнения в SQL), а чтение таблицы, содержащей 2 запроса, занимает сначала 3 секунды, а затем 9 секунд во второй.

В каждом столбце около 50 тыс. Строк и только 5 столбцов, из которых 2 - целые, 2 - двойные (с плавающей запятой на sql) и дата / время.Я попытался отключить буферизацию, но это не помогло.

Это потому, что Dapper сначала запрашивает базу данных только для того, чтобы выполнить запросы.Затем снова подключается к базе данных по запросу на чтение и получает все данные для конкретного чтения?

Было бы лучше просто создать несколько асинхронных задач, которые выполняются вместе с одним запросом каждая?

1 Ответ

0 голосов
/ 29 октября 2018

Я видел много вопросов по этому поводу и объяснения Марка Гравелла о том, почему он не хочет продолжать играть с несколькими сетками на более щадящем

Наиболее вероятная причина в том, что мы выполняемзапрос, который дает несколько результатов, используя MARS - Multiple Active Result Sets, но вы все равно не можете получить доступ ко всем наборам результатов за один раз.Они могут быть прочитаны последовательно, поскольку они выполняются изнутри с использованием функции NextResult DataReader.Для приложения это по-прежнему 1 вызов, когда в идеале одно и то же с использованием нескольких асинхронных вызовов всегда будет извлекать все результирующие наборы параллельно (идеальное использование системы / ресурса)

Относительно вашего запроса:

queries.Select(q => grid.Read<T>()).AsList();

Я предполагаю, что все ваши наборы результатов имеют одинаковый type T, а конечный результат, который вы получаете, имеет тип List<IEnumerable<T>>.

Теперь у вас есть возможность изменить ваши запросы, используя Async-Await следующим образом:

var grid = await context.QueryMultipleAsync(string.Join(";",selectCommands));
return queries.Select(q => await grid.ReadAsync<T>()).AsList();

Поможет ли это?

Чтобыв ограниченной степени, делая операции асинхронными, но преимущество будет ограниченным, поскольку все равно чтение будет последовательным с использованием MARS.

Теперь основная часть вашего запроса,

В этом случаеДля выполнения QueryMultiple требуется около 3 секунд (что в значительной степени соответствует времени выполнения в SQL), а чтение таблицы, содержащей 2 запроса, занимает сначала 3 секунды, а затем 9 секунд.

Это удивительно, чтение - единственная операция, выполненная здесь, запрос уже выполнен.Мы используем DataReader, который уже подключен, то же самое для Dapper GridReader, который является оберткой над DataReader.Если только чтение занимает так много времени, что и для записей размером 50 КБ, вам может понадобиться выяснить другие влияющие параметры, такие как скорость сетевого ввода-вывода, превышение лимитом памяти / ОЗУ, которые являются внешними факторами, оказывающими огромное влияние.

Это потому, что Dapper сначала запрашивает базу данных только для того, чтобы выполнить запросы.Затем снова подключается к базе данных по запросу на чтение и получает все данные для конкретного чтения?

Всегда лучшая стратегия по следующей причине:

  1. Высокая масштабируемостьподход
  2. База данных может выполнять несколько запросов одновременно, для чего она спроектирована
  3. Нет последовательного сбора / чтения результатов

Сказав это, я все еще удивлен, что просто чтение 50Kзаписи, так медленно, это должны быть внешние факторы.Переключение настроек буфера не окажет существенного влияния только на записи размером 50 КБ, которые хорошо сжимаются с помощью двоичной сериализации, обычно предпочтительным параметром является включение буфера, так как его оптимизация


Edit 1

Первое, что вы должны попробовать - запустить тот же тестовый пример на относительно высоком оборудовании, более высокой оперативной памяти, большем количестве процессоров, лучшем сетевом вводе-выводе, просто чтобы понять, принесут ли изменения в аппаратные средства улучшение, поскольку Dapper уже оптимизирован, даже если выиспользуйте QueryMultiple и считывайте GridReader

...