My program has a lot of simple select queries. Most of them are of the "select count() from... " variety. These are very simple queries where there is a single WHERE clause and the columns referenced are either a primary key column or another indexed column.

I would expect the database to keep the indexes in memory and thus have virtually no need to go to disk when doing these count() queries and such. Yet when I do an strace on the process, I see significant read() and seek() calls on the database file. What are the conditions for when it needs to read from the database file?

My database file is only around 4MB and I have set the default_cache_size to 50000. From what I've read, that should translate to almost 50MB of cache size which would be more than enough to keep the entire database in memory, I'd think. Yet it doesn't seem to actually do that since it is reading from the file so often.

I've seen this on OSX and Linux but this strace output is from Linux:
Snippet of strace output:

fcntl64(5, F_SETLK64, {type=F_RDLCK, whence=SEEK_SET, start=1073741824, len=1}, 0xbfffdb00) = 0 fcntl64(5, F_SETLK64, {type=F_RDLCK, whence=SEEK_SET, start=1073741826, len=510}, 0xbfffdb00) = 0 fcntl64(5, F_SETLK64, {type=F_UNLCK, whence=SEEK_SET, start=1073741824, len=1}, 0xbfffdb00) = 0
access("/db/data-journal", F_OK) = -1 ENOENT (No such file or directory)
fstat64(5, {st_mode=S_IFREG|0644, st_size=4402176, ...}) = 0
_llseek(5, 0, [0], SEEK_SET)            = 0
read(5, "SQLite format 3\0\4\0\1\1\0@ \0\0\4\200\0\0\0\0"..., 1024) = 1024
_llseek(5, 3072, [3072], SEEK_SET)      = 0
read(5, "\2\2]\0\22\1\214\6\0\0\16%\2\323\2\265\2z\2\361\3\245\3"..., 1024) = 1024
_llseek(5, 395264, [395264], SEEK_SET)  = 0
read(5, "\n\0\0\0$\0\\\0\0\\\0v\0\217\0\251\0\303\0\335\0\367\1"..., 1024) = 1024 fcntl64(5, F_SETLK64, {type=F_UNLCK, whence=SEEK_SET, start=0, len=0}, 0xbfffdfd0) = 0 fcntl64(5, F_SETLK64, {type=F_RDLCK, whence=SEEK_SET, start=1073741824, len=1}, 0xbfffdb60) = 0 fcntl64(5, F_SETLK64, {type=F_RDLCK, whence=SEEK_SET, start=1073741826, len=510}, 0xbfffdb60) = 0 fcntl64(5, F_SETLK64, {type=F_UNLCK, whence=SEEK_SET, start=1073741824, len=1}, 0xbfffdb60) = 0
access("/db/data-journal", F_OK) = -1 ENOENT (No such file or directory)
fstat64(5, {st_mode=S_IFREG|0644, st_size=4402176, ...}) = 0
_llseek(5, 0, [0], SEEK_SET)            = 0
read(5, "SQLite format 3\0\4\0\1\1\0@ \0\0\4\200\0\0\0\0"..., 1024) = 1024
_llseek(5, 2048, [2048], SEEK_SET)      = 0
read(5, "\5\0\0\0\2\3\364\0\0\0\n\253\3\372\3\364\0\0\0\0\0\0\0"..., 1024) = 1024
_llseek(5, 5120, [5120], SEEK_SET)      = 0
read(5, "\2\0\0\0\6\3\277\1\0\0\r\341\3\365\3\352\3\277\3\311\3"..., 1024) = 1024
_llseek(5, 1768448, [1768448], SEEK_SET) = 0
read(5, "\n\0\0\0q\0\370\0\0\370\0\377\1\6\1\f\1\22\1\30\1\36\1"..., 1024) = 1024
_llseek(5, 405504, [405504], SEEK_SET)  = 0
read(5, "\5\0\0\0\207\1(\0\0\0\1\207\1(\1-\0012\0017\1<\1A\1F\1"..., 1024) = 1024
_llseek(5, 137216, [137216], SEEK_SET)  = 0
read(5, "\r\0\0\0\1\1\35\0\1\35\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
_llseek(5, 293888, [293888], SEEK_SET)  = 0
read(5, "\r\0\0\0\2\0\217\0\0\217\3H\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
_llseek(5, 406528, [406528], SEEK_SET)  = 0
read(5, "\5\0\0\0|\1\30\0\0\0\n]\1\30\1\36\1$\1*\0010\0016\1<\1"..., 1024) = 1024
_llseek(5, 1178624, [1178624], SEEK_SET) = 0
read(5, "\r\0\0\0\2\0\353\0\0\353\3\221\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024
_llseek(5, 2127872, [2127872], SEEK_SET) = 0
read(5, "\r\0\0\0\3\0s\0\3\221\0s\0\342\0\0\0\0\0\0\0\0\0\0\0\0"..., 1024) = 1024

etc....

There is more or less a pattern that is very similar to the snippet above that repeats over and over in the trace. It sort of seems like it is reading a header or something in the database file over and over again.

Additional notes:
I set the following pragmas in this order when I create/open the database file (which only happens once when the app loads):
  PRAGMA auto_vacuum = 1
  PRAGMA temp_store = MEMORY
  PRAGMA synchronous = OFF
  PRAGMA default_cache_size = 50000

Thanks,
Sean

Reply via email to