簡體   English   中英

如何在Android中加快SQLite數據庫的插入速度?

[英]How can I speed up SQLite database insertions in Android?

在字典查詢應用程序中生成大量結果時,有時似乎每次插入都在500-1000 ms處停留。 有我不了解的插入技巧或竅門嗎?

這是插入的示例

long id = this.getDbAdapter().insertData(
    "combo",
     result.getWord(),
     String.valueOf(result.getNumLetters()),
     String.valueOf(result.getPointsScrabble()),
     String.valueOf(result.getPointsWordsWithFriends())
);
if (id < 0) {
    Log.i(TAG, "Database combo insertion of " + result.getWord() + " unsuccessful :(");
} else {
    Log.i(TAG, "Database combo insertion of " + result.getWord() + " successful :)");

}

這是我的數據庫適配器:我嘗試遵循Android准則...

/**
 * SQLite Database. There are many like it but this one is mine...
 *
 * @author John Doe
 * @author Citizen X
 * @version 0.2 (pre-beta)
 * @see 'http://developer.android.com/reference/android/database/sqlite/package-summary.html'
 * @since 0.1 2015-06-17.
 */

public class ResultsDbAdapter {

    // Debugging tag
    public final static String TAG = "DictionaryDbAdapter";

    // Result types
    private static final String RESULT_TYPE_ANAGRAM = "anagram";
    private static final String RESULT_TYPE_SUBWORD = "subword";
    private static final String RESULT_TYPE_COMBO   = "combo";

    // Handle for helper
    ResultsDbHelper helper;

    // Constructor gets access to inner helper class
    public ResultsDbAdapter(Context context) {
        helper = new ResultsDbHelper(context);
    }

    /* -------------- */
    /* --- Helper --- */
    /* -------------- */

    /**
     * SQLite open helper class
     */
     static class ResultsDbHelper extends SQLiteOpenHelper {

        public static final String TAG = "ResultsDbHelper";

        // If you change the database schema, you must increment the database version.
        public static final int DATABASE_VERSION = 55;
        public static final String DATABASE_NAME = "wordsleuth.db";

        /* ------------------------------ */
        /* --- Contract and constants --- */
        /* ------------------------------ */
        /**
         * Database contract
         */
        public class ResultsDbContract {

            // To prevent someone from accidentally instantiating the contract class,
            // give it an empty constructor.
            public ResultsDbContract() {}

            /* --- Inner class that defines the table contents --- */

            /*
            By implementing the BaseColumns interface, your inner class can inherit a primary key
            field called _ID that some Android classes such as cursor adaptors will expect it to have.
            It's not required, but this can help your database work harmoniously with the Android
            framework.
            */
            public abstract class ResultEntry implements BaseColumns {
                // Table name
                public static final String TABLE_NAME = "results";
                // Table columns
                public static final String UID = "_id";
                public static final String COLUMN_NAME_RESULT_TYPE = "resultype";
                public static final String COLUMN_NAME_WORD = "word";
                public static final String COLUMN_NAME_WORD_LENGTH = "length";
                public static final String COLUMN_NAME_SCRABBLE_POINTS = "scrabblepoints";
                public static final String COLUMN_NAME_WORDS_WITH_FRIENDS_POINTS = "wordspoints";
                // Table text
                private static final String ID_INCREMENT = " INTEGER PRIMARY KEY AUTOINCREMENT";
                private static final String TEXT_TYPE = " TEXT";
                private static final String INTEGER_TYPE = " INTEGER";
                private static final String AND = " AND ";
                private static final String COMMA_SEP = ", ";
                private static final String PARENTHESIS_LEFT = " (";
                private static final String PARENTHESIS_RIGHT = " )";
                // Table commands
                private static final String CREATE_TABLE = "CREATE TABLE ";
                private static final String DROP_TABLE = "DROP TABLE IF EXISTS ";
                private static final String DELETE_FROM_ALL = "DELETE * FROM ";
                // Table creation
                private static final String SQL_CREATE_ENTRIES =
                        CREATE_TABLE + TABLE_NAME + PARENTHESIS_LEFT +             // Create table
                            UID + ID_INCREMENT + COMMA_SEP +                       // _id
                            COLUMN_NAME_RESULT_TYPE + TEXT_TYPE + COMMA_SEP +      // result type
                            COLUMN_NAME_WORD + TEXT_TYPE + COMMA_SEP +             // word
                            COLUMN_NAME_WORD_LENGTH + TEXT_TYPE + COMMA_SEP +      // word length
                            COLUMN_NAME_SCRABBLE_POINTS + TEXT_TYPE + COMMA_SEP +  // sc points
                            COLUMN_NAME_WORDS_WITH_FRIENDS_POINTS + TEXT_TYPE +    // wwf points
                        PARENTHESIS_RIGHT;
                // Table deletion
                private static final String SQL_DELETE_ENTRIES = DROP_TABLE + TABLE_NAME;
                private static final String SQL_DELETE_ALL_ENTRIES = DROP_TABLE + TABLE_NAME;

            }
        }// End contract

        /* ------------------- */
        /* --- Constructor --- */
        /* ------------------- */

        /**
         *
         * @param context - the context
         */
        public ResultsDbHelper(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
            Log.i(TAG, "Database " + DATABASE_NAME + " version " + DATABASE_VERSION + " created");
        }



    /* -------------------------- */
    /* --- Database insertion --- */
    /* -------------------------- */

    /**
     * Insert a result into the database
     * @param resultType
     * @param word
     * @param length
     * @param scrabblePoints
     * @param wordsPoints
     * @return
     */
    public long insertData(
            // Insertion types       // Info
            // ---------------       --------------
            String resultType,       // Result type
            String word,             // The word
            String length,           // The length
            String scrabblePoints,   // Scrabble(TM) point value
            String wordsPoints       // Words With Friends(TM) point value
    ) {
        // Insert data
        SQLiteDatabase db = helper.getWritableDatabase();
        ContentValues contentValues = new ContentValues();
        contentValues.put(COLUMN_NAME_RESULT_TYPE, resultType);
        contentValues.put(COLUMN_NAME_WORD, word);
        contentValues.put(COLUMN_NAME_WORD_LENGTH, length);
        contentValues.put(COLUMN_NAME_SCRABBLE_POINTS, scrabblePoints);
        contentValues.put(COLUMN_NAME_WORDS_WITH_FRIENDS_POINTS, wordsPoints);
        // Returns -1 if fails, otherwise, returns
        return db.insert(TABLE_NAME, null, contentValues);
    }//End insertData()

    // Handle for helper
    ResultsDbHelper helper;

    // Constructor gets access to inner helper class
    public ResultsDbAdapter(Context context) {
        helper = new ResultsDbHelper(context);
    }

    /* -------------- */
    /* --- Helper --- */
    /* -------------- */

    /**
     * SQLite open helper class
     */
     static class ResultsDbHelper extends SQLiteOpenHelper {

        public static final String TAG = "ResultsDbHelper";

        // If you change the database schema, you must increment the database version.
        public static final int DATABASE_VERSION = 55;
        public static final String DATABASE_NAME = "wordsleuth.db";

        /* ------------------------------ */
        /* --- Contract and constants --- */
        /* ------------------------------ */
        /**
         * Database contract
         */
        public class ResultsDbContract {

            // To prevent someone from accidentally instantiating the contract class,
            // give it an empty constructor.
            public ResultsDbContract() {}

            /* --- Inner class that defines the table contents --- */

            /*
            By implementing the BaseColumns interface, your inner class can inherit a primary key
            field called _ID that some Android classes such as cursor adaptors will expect it to have.
            It's not required, but this can help your database work harmoniously with the Android
            framework.
            */
            public abstract class ResultEntry implements BaseColumns {
                // Table name
                public static final String TABLE_NAME = "results";
                // Table columns
                public static final String UID = "_id";
                public static final String COLUMN_NAME_RESULT_TYPE = "resultype";
                public static final String COLUMN_NAME_WORD = "word";
                public static final String COLUMN_NAME_WORD_LENGTH = "length";
                public static final String COLUMN_NAME_SCRABBLE_POINTS = "scrabblepoints";
                public static final String COLUMN_NAME_WORDS_WITH_FRIENDS_POINTS = "wordspoints";
                // Table text
                private static final String ID_INCREMENT = " INTEGER PRIMARY KEY AUTOINCREMENT";
                private static final String TEXT_TYPE = " TEXT";
                private static final String INTEGER_TYPE = " INTEGER";
                private static final String AND = " AND ";
                private static final String COMMA_SEP = ", ";
                private static final String PARENTHESIS_LEFT = " (";
                private static final String PARENTHESIS_RIGHT = " )";
                // Table commands
                private static final String CREATE_TABLE = "CREATE TABLE ";
                private static final String DROP_TABLE = "DROP TABLE IF EXISTS ";
                private static final String DELETE_FROM_ALL = "DELETE * FROM ";
                // Table creation
                private static final String SQL_CREATE_ENTRIES =
                        CREATE_TABLE + TABLE_NAME + PARENTHESIS_LEFT +             // Create table
                            UID + ID_INCREMENT + COMMA_SEP +                       // _id
                            COLUMN_NAME_RESULT_TYPE + TEXT_TYPE + COMMA_SEP +      // result type
                            COLUMN_NAME_WORD + TEXT_TYPE + COMMA_SEP +             // word
                            COLUMN_NAME_WORD_LENGTH + TEXT_TYPE + COMMA_SEP +      // word length
                            COLUMN_NAME_SCRABBLE_POINTS + TEXT_TYPE + COMMA_SEP +  // sc points
                            COLUMN_NAME_WORDS_WITH_FRIENDS_POINTS + TEXT_TYPE +    // wwf points
                        PARENTHESIS_RIGHT;
                // Table deletion
                private static final String SQL_DELETE_ENTRIES = DROP_TABLE + TABLE_NAME;
                private static final String SQL_DELETE_ALL_ENTRIES = DROP_TABLE + TABLE_NAME;

            }
        }// End contract

        /* ------------------- */
        /* --- Constructor --- */
        /* ------------------- */

        /**
         *
         * @param context - the context
         */
        public ResultsDbHelper(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
            Log.i(TAG, "Database " + DATABASE_NAME + " version " + DATABASE_VERSION + " created");
        }


        /**
         * On creation
         * @param db -  the database
         */
        public void onCreate(SQLiteDatabase db) {
            Log.i(TAG, "" + db.getPath() + " created");
            db.execSQL(ResultsDbContract.ResultEntry.SQL_CREATE_ENTRIES);
        }


    /* -------------------------- */
    /* --- Database insertion --- */
    /* -------------------------- */

    /**
     * Insert a result into the database
     * @param resultType
     * @param word
     * @param length
     * @param scrabblePoints
     * @param wordsPoints
     * @return
     */
    public long insertData(
            // Insertion types       // Info
            // ---------------       --------------
            String resultType,       // Result type
            String word,             // The word
            String length,           // The length
            String scrabblePoints,   // Scrabble(TM) point value
            String wordsPoints       // Words With Friends(TM) point value
    ) {
        // Insert data
        SQLiteDatabase db = helper.getWritableDatabase();
        ContentValues contentValues = new ContentValues();
        contentValues.put(COLUMN_NAME_RESULT_TYPE, resultType);
        contentValues.put(COLUMN_NAME_WORD, word);
        contentValues.put(COLUMN_NAME_WORD_LENGTH, length);
        contentValues.put(COLUMN_NAME_SCRABBLE_POINTS, scrabblePoints);
        contentValues.put(COLUMN_NAME_WORDS_WITH_FRIENDS_POINTS, wordsPoints);
        // Returns -1 if fails, otherwise, returns
        return db.insert(TABLE_NAME, null, contentValues);
    }//End insertData()



}

您可以實現的最簡單,最有效的性能提升之一就是管理數據庫事務。 有關交易的更多信息。

可以使用以下類似的方法來實現:

db.beginTransaction();
try {
  InsertData();
  db.setTransactionSuccessful();
} catch {
  //Error in between database transaction 
} finally {
  db.endTransaction();
}

此外,通過將標准連接字符串修改為數據庫,可以提高速度。 是進行各種速度改進的好資源,

在多個插入之間重用SQLiteStatement可以提高插入速度。

SQLiteDatabase db = helper.getWritableDatabase();
db.beginTransaction();
try {
    final SQLiteStatement insertStatement = db.compileStatement("INSERT INTO x (a,b) VALUES (?, ?);");
    for (Item item : itemsToInsert) {
        insertStatement.clearBindings();
        insertStatement.bindLong(1, item.getA());
        insertStatement.bindString(2, item.getB());
        insertStatement.executeInsert();
    }
    db.setTransactionSuccessful();
} finally {
    db.endTransaction();
}

如果您插入很多行,則與為每行執行一個新的插入語句相比,性能提高通常為2-3倍。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM