Channels ▼
RSS

Design

iOS Data Storage: Core Data vs. SQLite


Core Data provides a lot of tools and capabilities to handle almost any type of data. The downside is that has a lengthy learning curve.

Note: In the accompanying sample application, all Core Data code is located in the source files GB_CarsCoreData.m and .h.

SQLite

SQLite is an open source, lightweight, robust, well-supported, self-contained, cross-platform, relational database that is very popular. You have probably used SQLite at some point in the past — it is a very good option for storing application data. The SQLite website is worth taking a moment to browse. Unlike many open source projects, SQLite documentation and support is excellent. SQLite version 3.7.13 is supported on iOS 6 and 7. SQLite is also supported on Android and Windows phone, which is a huge benefit. If you are developing a mobile application targeting multiple platforms, you'd be crazy not to use SQLite.

SQLite stores data in tables, where a table contains one or more columns, each column contains data for a specific data type. One of the tasks RDMS are good at is handling a normalized data set. Instead of each table containing all of the possible columns of data, resulting in duplicated data for each table row, the tables are typically organized to reference another table (via a key), that contains the duplicated data. In the sample application, the manufacture information is kept in a separate mfg_info table which is referenced by the car table.

Your application interacts with SQLite via the SQL language and the SQLite C API (see sqlite.h). This means that to insert data into the database an insert SQL statement must be created along with the data to insert. The following snippet shows the insert statement used by the sample application.

"insert into car (model, msrp, year, mfg_id, cartype_id,
 cardetails_id) values ("Pinto", 17000, 1970, 1, 2, 3)"

Predictably, to fetch data a select SQL statement is needed. For example, the following snippet shows how a select statement is used to fetch all of the car records:

"select * from car"

This is the simple case where all of the car table information is fetched; however, things get complicated quickly when you want to get all of the information for a specific car. In the sample application, this means multiple join statements as show below:

"select car.model, car.year, car.msrp, cardetails.detailgroup, " 
"cardetails.info_1, cardetails.info_2, manufacturer.hq_location, " 
"manufacturer.name, manufacturer.num_employees, cartype.type, " 
"cartype.type_desc from car inner join cartype on " 
"car.cartype_id = cartype.id inner join cardetails on " 
"car.cardetails_id = cardetails.id inner join manufacturer on "
"car.mfg_id = manufacturer.id where car.id = %@"

As you can see, even a moderately involved data set requires a solid understanding of SQL syntax and behavior. Another drawback to SQLite is the tedious nature of ensuring that the columns and data are in the correct order. For example, when iterating through the SELECT results, if you make a mistake for the column number in the sqlite3_column_*() call, the wrong data will be fetched. This can easily happen when additional columns are added or removed later.

SQLite implements a C API; thus, you will have to convert between NSStrings * and char * strings when your application interacts with the database. There are Objective C wrappers for SQLite — the most popular being FMDB. For most applications, using the SQLite API directly is not overly cumbersome. The attached sample application uses the SQLite API directly.

Differences between Core Data and SQLite

Core Data and SQLIte are fundamentally different, so it is difficult to compare the two technologies directly. However, from a developer's viewpoint, you can gauge how these differences manifest themselves in an application. What is the cost and benefit of each approach? The accompanying sample iOS iPhone application is designed to test both technologies. From the main screen, select either Core Data or SQLite, create the desired number of records, and select the Car tab to fetch the records. The memory usage number is for the entire application and is updated once per second. The storage size is the size of the actual persistent file.

Using this test application, let's look at a few key metrics. An iPhone 4s and 5s were tested, both running iOS version 7.1.1. The type of iPhone used, 4s or 5s, for a result is show within parentheses. For exampe (4s) denotes test results for an iPhone 4s, (5s) is for an iPhone 5s.

Memory Usage

Core Data uses more memory, from 40% to 100% more than SQLite. This makes sense considering how Core Data is designed (specifically, how the NSManagedObjectContext tracks all of the objects), where each object has a memory footprint of some size depending on whether the object's contents have been faulted in (realized in memory versus being a fault).

Record Type

50,000 Recs

100,000 Recs

200,000 Recs

Core Data

32 MB (5s)

24 MB (4s)

53 MB (5s)

38 MB (4s)

91 MB (5s)

67 MB (4s)

SQLite

21 MB (5s)

16 MB (4s)

29 MB (5s)

22 MB (4s)

46 MB (5s)

36 MB (4s)

Table 3: Numbers after application start up and fetch of all Car records.

There is something to note about memory testing. When creating records, the entire Car record is created in memory and the higher memory usage reflects this. However, most user scenarios do not involve creating a large number of records. A better measurement of the memory usage is at application start up and with a fetch of all of the Car records. This is what Table 3 reflects. To get this measurement in testing, the application was restarted (terminated versus put in the background) and the records were re-fetched.

Storage Size

Core Data uses more storage space — a lot more storage space — approximately 4x more than SQLite, see Table 4.

Record Type

50,000 Recs

100,000 Recs

200,000 Recs

Core Data

6532 KB (5s)

6412 KB (4s)

13296 KB (5s)

13180 KB (4s)

27004 KB (5s)

2,912 KB (4s)

SQLite

1676 KB (5s)

1676 KB (4s)

3364 KB (5s)

3364 KB (4s)

6824 KB (5s)

6824 KB (4s)

Table 4.

Speed

Both Core Data and SQLite are fast when fetching records. For the iPhone 5s, the differences are slight. However, for the 4s, Core Data is nearly 2x as fast. Table 5 shows just one operation, fetching all of the Car records.

Record Type

Number of Records Fetched

50,000

100,000

200,000

Core Data

107 msec (5s)

397 msec (4s)

230 msec (5s)

850 msec (4s)

475 msec (5s)

1644 msec (4s)

SQLite

140 msec (5s)

730 msec (4s)

280 msec (5s)

1447 msec (4s)

580 msec (5s)

3077 msec (5s)

Table 5.

Conclusion

Here are some final key points about SQLite and Core Data to keep in mind:

SQLite:

  • SQLite is, as advertised, lightweight.
  • SQLite uses less memory and storage space.
  • SQLite can be tedious and error-prone to code.
  • SQLite is supported on Android and Microsoft Windows Phone.

Core Data

  • Longer learning curve: it takes some study to understand.
  • Objects are easier to work with.
  • Underlying storage details are handled atomically (support for iCloud).
  • Undo and Redo features.

No one technology, framework, or diet pill will make your life instantly better. When designing an application, a lot of criteria must be considered. This article provides some guidance when selecting a storage approach for your next iOS application. I encourage you to download the sample application and take it for a spin.


Dean Gereaux is a consultant engineer and principal of Golden Bits Software.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video