sql >> データベース >  >> RDS >> SQLite

シングルトンアプローチでのSQLiteメモリの問題

    開いているファイルが多すぎることを示すメッセージが表示された場合は、まだ開いているカーソルが多すぎることが原因である可能性があります。

    ただし、返されるメッセージは常に同じであるとは限らず、呼び出されているタスク/呼び出しに固有である可能性があります。

    この場合、メッセージは(unable to open database file (code 2062))でした。 、さらに別のケース(SELECTからのメッセージはunable to open database file (code 14) )。 SQLiteは、頻繁な「SELECT」クエリでデータベースファイル(コード14)を開くことができません。

    上記のリンクは、カーソルを作成すると1つまたは複数のファイルが開かれることを非常に明確に示している投稿も示しています。

    この例では、約500行をループし、各行に対して、各行に対して3つのカーソルを作成/再作成していました(したがって、4つのカーソルオブジェクトのみを使用している場合でも、1500以上のカーソルが存在する可能性があります)。

    最初は、最後(すべての親の最後の行)で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. 2013 MVPサミット:簡単なレビューと展望

    2. SelectQueryでGroupbyを使用してHaving句を適用する方法-SQLServer/TSQLチュートリアルパート131

    3. pg_upgradeを使用してLinuxでTimescaleDBとPostGISを使用してPostgreSQL11をPostgreSQL13にアップグレードする

    4. ALTERTABLEステートメントに「ONDELETECASCADE」を追加する方法