iOS FMDB извлекает около трех миллионов элементов: завершается из-за проблем с памятью

Недавно я работаю над приложением о sqlite. Я использовал FMDB (2.6.2), а iOS - 10.2.0 . В базе данных около трех миллионов предметов. И у каждого предмета есть три колонны:idnamelogo,

При отображении всех данных на пользовательском интерфейсе, требования приложения унесены:

  • Вы не можете использовать способ получения большего количества данных (так же, как использовать UITableView или же UICollectionView прокрутите вниз, чтобы загрузить больше, но вы все еще можете использовать UITableView или же UICollectionView)
  • Пользовательский интерфейс должен быть очень плавным при прокрутке
  • Не вызывает переполнение памяти

Согласно требованиям, я проверяю некоторые условия.

Я могу удовлетворить первое и второе требование. Но последнее, я обнаружил, что когда вы выбираете все три миллиона элементов из БД один или много раз, это все равно может вызвать переполнение памяти.

Вот мой код для извлечения данных в фоновой очереди:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    while (_usersArrM.count < _countNum)
    {
        NSUInteger offset = _usersArrM.count + usersFromDBOffsetCount;
        if (offset > _countNum)
        {
            offset = _countNum - _usersArrM.count;
        }
        else
        {
            offset = usersFromDBOffsetCount;
        }

        NSString  *sql = [NSString stringWithFormat:@"select * from user limit %zd, %zd", _usersArrM.count, offset];

        [_queue inDatabase:^(FMDatabase *db) {

            FMResultSet *userModelRS = [db executeQuery:sql];
            while (userModelRS.next)
            {
                AndyUserModel *userModel = [[AndyUserModel alloc] init];

                userModel.Id = [userModelRS intForColumn:@"id"];
                userModel.name = [userModelRS stringForColumn:@"name"];
                userModel.logo = [userModelRS stringForColumn:@"logo"];
                [_usersArrM addObject:userModel];
            }

            [userModelRS close];
        }];

        [_queue close];
    }
});

Подсказки:

  • _usersArrM: NSMutableAarray источник данных UITableView
  • _countNum: количество предметов в дБ
  • usersFromDBOffsetCount: static NSUInteger const usersFromDBOffsetCount = 2000;
  • _queue: _queue = [FMDatabaseQueue databaseQueueWithPath:dbPath];
  • скачать БД: http://okufme2fh.bkt.clouddn.com/test.db.zip

Я думаю, проблема, которая вызывает переполнение памяти _queue, даже если [_queue close], некоторая память о БД не может быть освобождена правильно. И результат в том, что когда цикл несколько раз, приложение закрывается из-за проблемы с памятью.

Есть ли один способ полностью освободить память БД, когда закончится один цикл. Или как правильно удовлетворить эти требования для этого приложения.

Благодарю.

1 ответ

В какой-то момент, независимо от того, насколько хороша ваша структура данных, само выделение памяти приведет к сбою любого оборудования, недостаточно мощного для его обработки. Вы можете попытаться извлечь данные, которые вы пытаетесь получить (т.е.

SELECT specific_col_1, specific_col_2, ... FROM table WHERE conditions

где specific_col_i является низким значением потребления памяти в среднем.

Другой гарантией будет использование OFFSET а также LIMIT чтобы ограничить объем данных, которые вы извлекаете из базы данных в любой момент времени:

SELECT specific_col_1, specific_col_2, ... FROM table WHERE conditions LIMIT x OFFSET j

где x - это безопасное количество записей, которые нужно извлечь и обработать за один раз, а j - индекс последнего числа найденных строк. Возможно, вам придется "играть" со значениями x а также j,

Скорее всего, вам придется использовать интеллектуальный алгоритм зацикливания, чтобы выборочно "вводить и обрабатывать" все эти записи. И вы можете хранить партии, которые вы получаете от циклов, в сторону, в другой таблице / базе данных, если это необходимо (точно не знаете, что вам нужно для обработки данных, когда данные вводятся или после ввода данных).

Наконец, вы можете найти LabQLite полезным. Это библиотека, которую я разработал для работы с SQLite в приложении для iOS. LabQLite Model Generator - это созданный мной генератор моделей, который позволит вам рассматривать ваши таблицы и представления как классы в Objective-C (или Swift, если вы выполняете код взаимодействия)). В LabQLite также имеется множество средне- и низкоуровневых методов контроллера баз данных, которые могут помочь в уточнении процесса циклирования / пакетирования, о котором я упоминал выше.

Другие вопросы по тегам