0

I seem to be getting stuck at 500-1000 ms per insert at some point, when generating large sets of results in a dictionary querying app. Are there any tips or tricks to insertion that I'm not understanding?

Here is an example of an insert

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 :)");

}

Here is my database adapter: I tried to follow Android guidelines...

/**
 * 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()



}

2 Answers2

3

One of the easiest and most effective performance gains you can achieve is to mange The database transaction. For more on Transactions.

This can be implemented by using something like the following:

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

Further by modifying to the standard connection string to the database can yield some improve speeds. This is a great resource for various speed improvements,

Community
  • 1
  • 1
Helix 88
  • 701
  • 6
  • 19
-1

Reusing a SQLiteStatement between multiple inserts is known to boost insertion speed.

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();
}

Performance gains are usually 2-3x compared to executing a new insert statement for each row, if you insert many of them.

BladeCoder
  • 12,779
  • 3
  • 59
  • 51