SQLite
 sql >> база данни >  >> RDS >> SQLite

Проблем с паметта на SQLite с единичен подход

Ако получавате съобщение, показващо твърде много отворени файлове, причината може да е, че има твърде много курсори, които все още са отворени.

Въпреки това, върнатото съобщение може да не винаги е същото и вероятно е специфично за задачата/повикването, което се извиква.

В този случай съобщението беше (unable to open database file (code 2062)) , но в друг случай (от SELECT съобщението беше unable to open database file (code 14) ). SQLite не може да отвори файл на база данни (код 14) при честа заявка „SELECT“.

Горната връзка също сочи към публикация, която направих, което съвсем ясно показва, че създаването на курсор води до отваряне на файл (или файлове).

Примерът минаваше през около 500 реда и за всеки ред създаваше/пресъздаваше 3 курсора за всеки ред (така че потенциално 1500+ курсора, въпреки че използва само 4 обекта на курсора).

Първоначално затваряше само 3-те курсора в края (последния ред на родителя на всички), което води до unable to open database File (code 14) . Затварянето на 3-те курсора за всяка итерация реши проблема.

Неуспешният код беше :-

        SQLiteDatabase db = getWritableDatabase();
        Cursor shoplistcursor = getAllRowsFromTable(SHOPLIST_TABLE_NAME);
        Cursor productcsr;
        Cursor aislecsr;
        Cursor prdusecsr;
        while(shoplistcursor.moveToNext()) {
            productcsr = getProductFromProductId(shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_PRODUCTREF)));
            aislecsr = getAisleFromAisleId(shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_AISLEREF)));
            prdusecsr = getProductUsage(shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_AISLEREF)),
                    shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_PRODUCTREF)));
            if (productcsr.getCount() < 1 | aislecsr.getCount() < 1 | prdusecsr.getCount() < 1) {
                deleteShopListEntry(shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_ID)));
            } 
            if(shoplistcursor.isLast()) {
                prdusecsr.close();
                aislecsr.close();
                productcsr.close();
            }
        }
        shoplistcursor.close();
        db.close();
}

Докато фиксираният код беше :-

        SQLiteDatabase db = getWritableDatabase();
        Cursor shoplistcursor = getAllRowsFromTable(SHOPLIST_TABLE_NAME);
        Cursor productcsr;
        Cursor aislecsr;
        Cursor prdusecsr;
        while(shoplistcursor.moveToNext()) {
            productcsr = getProductFromProductId(shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_PRODUCTREF)));
            aislecsr = getAisleFromAisleId(shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_AISLEREF)));
            prdusecsr = getProductUsage(shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_AISLEREF)),
                    shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_PRODUCTREF)));
            if (productcsr.getCount() < 1 | aislecsr.getCount() < 1 | prdusecsr.getCount() < 1) {
                productcsr.close();
                aislecsr.close();
                prdusecsr.close();
                deleteShopListEntry(shoplistcursor.getLong(shoplistcursor.getColumnIndex(SHOPLIST_COLUMN_ID)));
            } else {
                productcsr.close();
                aislecsr.close();
                prdusecsr.close();
            }
        }
        shoplistcursor.close();
        db.close();
    }

Сега съм склонен да следвам следното правило/практика :-

  • Ако просто получавате резултата, напр. като получите броя на редовете, затворете курсора в метода.

  • Ако използвате курсора за дисплей, напр. ListView, след което затворете курсора в onDestroy на дейността метод.

  • Ако използвате курсора за това, което ще нарека по-сложна обработка, напр. изтриване на редове с основни препратки, след което затворете курсорите веднага щом приключат, в рамките на цикъла(ите) за обработка.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. 5 начина да стартирате SQL скрипт от файл в SQLite

  2. Android – Курсор onMapReady (Маркери)

  3. Интегриране на SQLCipher с greenDAO

  4. Няма такава колона sqlite изключение

  5. Грешка в SQLiteDatabase, неполезен дневник