Я видел много вопросов по этому поводу и объяснения Марка Гравелла о том, почему он не хочет продолжать играть с несколькими сетками на более щадящем
Наиболее вероятная причина в том, что мы выполняемзапрос, который дает несколько результатов, используя 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 сначала запрашивает базу данных только для того, чтобы выполнить запросы.Затем снова подключается к базе данных по запросу на чтение и получает все данные для конкретного чтения?
Всегда лучшая стратегия по следующей причине:
- Высокая масштабируемостьподход
- База данных может выполнять несколько запросов одновременно, для чего она спроектирована
- Нет последовательного сбора / чтения результатов
Сказав это, я все еще удивлен, что просто чтение 50Kзаписи, так медленно, это должны быть внешние факторы.Переключение настроек буфера не окажет существенного влияния только на записи размером 50 КБ, которые хорошо сжимаются с помощью двоичной сериализации, обычно предпочтительным параметром является включение буфера, так как его оптимизация
Edit 1
Первое, что вы должны попробовать - запустить тот же тестовый пример на относительно высоком оборудовании, более высокой оперативной памяти, большем количестве процессоров, лучшем сетевом вводе-выводе, просто чтобы понять, принесут ли изменения в аппаратные средства улучшение, поскольку Dapper уже оптимизирован, даже если выиспользуйте QueryMultiple
и считывайте GridReader