SQLite Bulk Insert

February 19, 2012 06:13 by wjchristenson2

“Bulk Insert” for SQLite does not exist.  However, there are some tricks to speed up bulk loading of SQLite data.  In this post, I am going to show you some techniques that I’ve learned to load data as fast as possible into a SQLite database.

First, every SQL statement ran on SQLite is ran under a transaction even if you don’t specify one.  When loading thousands of records, this can be very taxing and slow things down very fast.  As a result, you’ll want to load all records under one transaction so that the SQLite DBMS will not start/commit a transaction for every row.

Second, use prepared statements and/or reuse your SQLiteCommand objects.  What you do is dependent on what technology you are using SQLite with (e.g. Java for Android or ADO.NET).  Rebuilding objects for every record inserted is very taxing.  So you’ll want to build the object once, then pass values to it for each row.

In summary, do the following for quick “bulk inserts”:
1)  Use 1 transaction to load all records.
2)  Reuse command/prepared statements to insert each row.

Here’s a snippet on how to bulk insert in Java for Android:

db.beginTransaction();
try {
	SQLiteStatement insert = null;
	insert = db.compileStatement("INSERT OR REPLACE INTO \"MyTable\" ("
			+ "\"MyColumnName\") VALUES (?)");
	
	for (i = 0; i++; i < 10000)
	{
		insert.bindLong(1, i);
        insert.execute();
		insert.clearBindings();
	}
	
	db.setTransactionSuccessful();
}
catch (Exception e) {
	String errMsg = (e.getMessage() == null) ? "bulkInsert failed" : e.getMessage();
	Log.e("bulkInsert:", errMsg);
}
finally {
	db.endTransaction();
}

 

Here’s an example of how to bulk insert in VB .NET:

        Using sqliteConn As SQLiteConnection = New SQLiteConnection("Data Source=c:\test.s3db")

            Dim sqliteTran As SQLiteTransaction = Nothing

            Try
                Dim sql As StringBuilder = New StringBuilder()
                sql.Append("INSERT INTO ""MyTable""(""MyColumnName"") VALUES (:MyColumnName);")

                Dim cmdSQLite As SQLiteCommand = sqliteConn.CreateCommand()
                With cmdSQLite
                    .CommandType = CommandType.Text
                    .CommandText = sql.ToString()
                    cmdSQLite.Parameters.Add(":MyColumnName", DbType.Int64)
                End With

                Dim i As Integer = 0
                While i < 10000
                    cmdSQLite.Parameters(":MyColumnName").Value = i
                    cmdSQLite.ExecuteNonQuery()

                    i += 1
                End While

                sqliteTran.Commit()
            Catch ex As Exception
                'attempt to rollback the transaction
                Try
                    sqliteTran.Rollback()
                Catch ex2 As Exception
                    'do nothing
                End Try

                'rethrow the exception
                Throw (ex)
            End Try
        End Using

 

Both examples insert 10,000 records.  Notice that we explicitly kick off one transaction for all inserts and commit it after we are finished inserting.  Also notice that in both examples, one command/prepared statement is built and reused for all 10,000 inserts.  There are some other SQLite tweaks you can do to slightly speed up performance, but the 2 mentioned will give you the most gains without having to get too technical with the SQLite DBMS engine.


Bookmark and Share

WPF Data Binding Troubleshooting Tips

December 10, 2011 05:05 by wjchristenson2

This week I ran into a WPF data binding problem and spent about a day trying to figure out why it wasn’t working.  A day is a long time to spend on why a “Text” property is not binding to an object’s property which is of the type “String”.  Here’s some quick tips on identifying the source of the data binding problem.

1)  Ensure Data Binding Debugging Information shows in Visual Studio’s Output window.  Visual Studio has the capability of showing verbose data binding trace information.  This can help you get to the bottom of the issue quickly.  In my case, my output window was not showing any data binding information…  You’ll need to adjust some Visual Studio debugging options.  First, ensure that all debugging information is not being sent to the immediate window.  Tools >> Options >> Debugging >> “Redirect all Output Window text to the Immediate Window”.  Uncheck that.  Next, Tools >> Options >> Debugging >> Output Window >> WPF Trace Settings >> Data Binding.  Select an option here.  When I was debugging I wanted to see everything going on so I selected “Verbose”.  Unfortunately, the information did not tell my anything as to why my two-way binding was not updating the underlying object’s property…

 

2)  Understand Dependency Properties and the INotifyPropertyChanged interface.  In order for the UI to properly show object property changes or to perform two-way binding, the property which it binds to needs to be a dependency property or the object needs to implement the INotifyPropertyChanged interface so that the UI properly reflects the object’s property changes and the UI can also update the object’s properties (if two-way binding is enabled).  In my case, my UI control was bound to a dependency property which its type also implemented INotifyPropertyChanged and my two-way binding still didn’t work…

 

3)  Are you using a Converter in the data binding expression?  Sometimes converters can throw exceptions and break the binding.  Put breakpoints in your converter and ensure the conversions are not throwing exceptions and breakpoints are being hit.  In my case, the convert from was being hit, but the convert back (updating the object from the UI via two-way data binding) was not being hit.  So one-way was working, but two-way was not…

 

4)  Are you binding a Custom Control which overrides/overloads the property which you are wanting to bind to?  This was the problem for me.  I was wanting to two-way bind the “Text” property of a custom user control to my object’s property.  The custom control was inheriting from TextBox and they were overloading the “Text” property.  Apparently this broke the two-way data binding.  I figured it out by simply dropping a vanilla TextBox onto my UI and binding it’s “Text” property to my expression and two-way binding worked great.  So, when things get really hairy, simplify what you are doing and add more and more things back into the picture until something breaks.  Troubleshooting 101 for the win.

Bookmark and Share

C of O 2011 Activity

December 3, 2011 06:20 by wjchristenson2

In case some of my readers do not know, I am a College of the Ozarks alumnus and I currently work for HealthMEDX.  I graduated from the C of O Computer Sciences Program in 2001.  Over the past year, I’ve had some great opportunities to assist C of O students and faculty.  I was able judge senior projects in May.  In July, HealthMEDX invited C of O faculty to share in its success with MO Governor Jay Nixon and HMX C of O alumni in the form of an incentives announcement.  In October, I was able to guest lecture on n-Tier application development and I recently had the opportunity to speak at the ACM Meet & Greet.  I wanted this post to serve as a big thanks to HealthMEDX for the chance to help assist the C of O Computer Sciences Program.  I’d also like to thank C of O students and faculty for the invitations to do so.  I truly hope that my experiences and knowledge help the program.

 

July of 2011 – C of O Faculty and Alumni (now HealthMEDX employees) with MO Governor Jay Nixon at a press release event in which an economic incentive package was announced to help generate 65 new jobs at HealthMEDX.

 

December of 2011 – ACM Meet and Greet - C of O alumni gave their career experiences and provided tips on: interviewing, landing the first job, and what to expect after graduation.  Guest Speakers: Melissa Wagner (FedEx), Bill Christenson (HealthMEDX), Joel Cash (Cerner).

Bookmark and Share

Android Version History

November 5, 2011 12:18 by wjchristenson2

If you are like me, you may be confused with all of the Android release code names.  Something I learned today is that the code names are in alphabetical order.  So if 5.0 is Jelly Bean, my wild guess is 6.0 will be Kiwi…

 

Distribution API Level
5.0 Jelly Bean 15-16
4.0 Ice Cream Sandwich 14-15
3.x.x Honeycomb 11-13
2.3.x Gingerbread 9-10
2.2 Froyo 8
2.1 Eclair 7
1.6 Donut 4
1.5 Cupcake 3


Something else I learned today… don’t set your SD card size to 16gb for your AVD.  It literally takes up 16gb of HD space and takes forever to allocate.  :(

Bookmark and Share

Android Virtual Devices

October 9, 2011 12:23 by wjchristenson2

In my last two posts on Android, I went over how to setup your machine to program for Android and I also went over how to create an Android project.  In this post I’m going to go over Android Virtual Devices and how they are used in Android development.  An Android Virtual Device (AVD) is an emulator configuration which models an Android device.  Before you can run your application, you have to define an AVD to run and test it on.  Setting up an AVD is very easy using the AVD Manager integrated into Eclipse.

To setup a new AVD in Eclipse, you’ll need to navigate to “Window >> Android SDK and AVD Manager”.  Click the Virtual Devices option on the left side.  I will show you how to create a Gingerbread (Android 2.3) AVD.  To create the AVD, click the “New” button and fill out the options as shown below.  Click “Create AVD” when you are finished.

Copying the options I have set above will create a generic Android Gingerbread emulator to use.  Next, I’ll briefly touch on what each of the AVD options do.

Name:  The name of the AVD.

Target:  The API level to which you want to test against.  Typically this is the API level that you setup for your application’s build target.  The AVD target level must be greater than or equal to what your application is set to.

CPU/ABI:  This is intended for Android devices which run on non-ARM processor architectures.  From my research, I’ve not seen any devices that supported such.

SD Card:  The size of the SD card.

Snapshot:  This option is a newer option which helps speed up the starting of the Android emulator.  You can enable this so that the emulator will launch quicker and when you stop it, it will save its state.  You can disable the save to snapshot after you’ve saved it once in the state you want to help it close faster.  On my machine, it’s still slow to start… but maybe that’s just my laptop’s poor disk speed.

Skin:  The skin of the emulated Android device.  HVGA is default.  You can download custom skins.

Hardware:  You can define all sorts of custom settings to emulate (e.g. RAM size).  I’m not going to list them here, but you can view the list here.

Override the existing AVD with the same name:  If you have an existing AVD created that has the same name as you just named this AVD device, it will override the old one.

Bookmark and Share