IEnumerable Collection - исключение нехватки памяти - PullRequest
0 голосов
/ 06 сентября 2018

У меня есть код в моем консольном приложении C #, который запрашивает БОЛЬШОЙ набор данных в SQL и добавляет его в коллекцию IEnumerable, которую я использую для последующей итерации в приложении. В таблице SQL, которая возвращает менее 100 тыс. Строк, она прекрасно работает, но я должен использовать это для перебора 100 миллионов записей. После выполнения запроса SQL и Dapper пытается заполнить коллекцию, я получаю OUT OF MEMORY ошибка исключения. Я почти уверен, что это потому, что он пытается написать 100 миллионов объектов одновременно. Есть ли способ, которым я могу пакетировать коллекцию не более, чем, скажем, 500К объектов, сделать то, что мне нужно сделать, затем вернуться и обработать еще 500К и так далее? По сути, мне нужно ЧИТАТЬ из записей SQL 500K, затем записать их в файл, прочитать еще 500K, записать в другой файл.

    public List<AxDlsd> GetDistinctDlsdObjects(AxApp axApp, OperationType operationType)
    {

        if (operationType == OperationType.Assessment)
        {

            string query = $"SELECT DISTINCT(clipid) from {axApp.dlname}";
            using (var connection = _dbConnectionFactory.GetAxDbConnection())
            {
                //SqlMapper.Settings.CommandTimeout = 0;
                List<AxDlsd> dlsdrecord = new List<AxDlsd>();

                return connection.Query<AxDlsd>(query, commandTimeout: 0, buffered: false ).ToList();

            }
        }

1 Ответ

0 голосов
/ 06 сентября 2018

Вы можете сделать SELECT COUNT(DISTINCT clipid) from {axApp.dlname}, чтобы получить итоговую сумму, а затем использовать ее на странице

int pageSize = 500000;

for(var page = 0; page < (total / pageSize) + 1; page++)
{
    string query = $"SELECT DISTINCT(clipid) from {axApp.dlname} ORDER BY clipid OFFSET {page * pageSize} FETCH NEXT {pageSize} ROWS ONLY";
    ///...
}

Это позволит вам просматривать 500 тыс. Строк за раз или независимо от того, какой у вас размер страницы. FETCH / OFFSET требует SQL Server 2012. Я не уверен, какой SQL вы используете.

...