Pickle and sqlite - loading and saving recarray's

Vincent Nijs <v-nijs-GCdv8E9reVRqeCPtdOfA2ld870/[email protected]>
Newsgroups gmane.comp.python.db.pysqlite.user
Message-ID <C2C6FF8F.842D%[email protected]>
I posted the message below on the numpy discussion list. Few if any people
there seem to use sqlite.

I am interesting in using sqlite to store data for scientific research. I
wrote the attached test program to save and load a simulated 11x500,000
recarray (a common array type in Numpy). Average save and load times are
given below (timeit with 20 repetitions). The save time for sqlite is not
really fair because I have to delete the data table each time before I
create the new one. It is still pretty slow in comparison. Loading the
recarray from sqlite is significantly slower than cPickle. I am hoping there
may be more efficient ways to save and load recarray¹s from/to sqlite than
what I am now doing. Note that I infer the variable names and types from the
data rather than specifying them manually.

saving recarray with cPickle:       1.448568 sec/pass
saving recarray with sqlite:         193.286204 sec/pass

loading recarray using cPickle:    0.471365 sec/pass
loading recarray with sqlite:        15.977018 sec/pass

To run the test you do need numpy (http://www.scipy.org/Download)

I did get an interesting response on this issues from Francesc Altet
(designer of pytables) on the numpy-list that might (or might not :) ) be of
interest to readers of the pysqlite list.

http://permalink.gmane.org/gmane.comp.python.numeric.general/16221

Best,

Vincent

_______________________________________________
pysqlite mailing list
pysqlite-IAPFreCvJWPBWskQ1e/[email protected]
http://lists.initd.org/mailman/listinfo/pysqlite
load_sqlite_test.py (application/octet-stream, 3.3 KB)
def test_pickle_save(fname):
	# saving recarray as a pickle file
	f = open('%s.pickle' % fname,'wb')
	cPickle.dump(data,f,2)
	f.close()

def test_pickle_load(fname):
	# loading recarray from pickle file
	f = open('%s.pickle' % fname,'rb')
	data = cPickle.load(f)
	f.close()

def test_save_sqlite(fname, table = 'data'):
	# saving recarray to an sqlite file
	conn = sqlite3.connect('%s.sqlite' % fname)

	c = conn.cursor()

	# getting the variable names
	varnm = data.dtype.names
	nr_var = len(varnm)

	# transform to types sqlite knows
	types = []
	for i in data[0]:
		if type(i) == N.string_: types.append('text')
		if type(i) == N.float_: types.append('real')
		if type(i) == N.int_: types.append('integer')
	
	create_string = ",".join(["%s %s" % (v,t) for v,t in zip(varnm,types)])

	# create a table if it doesn't exist yet
	try:
		c.execute('drop table %s' % table)
	except sqlite3.OperationalError:
		pass

	c.execute('create table %s (%s)' % (table,create_string))

	# putting the data into the table
	exec_string = 'insert into %s values %s' % (table,'(%s)' % (','.join(('?')*nr_var)))
	c.executemany(exec_string, data)

	# commiting the data to the database
	conn.commit()

	# closing the connection
	conn.close()

def test_load_sqlite(fname, table = 'data', str_length = 20):

	conn = sqlite3.connect('%s.sqlite' % fname)
	c = conn.cursor()

	# get all data
	c.execute('select * from %s' % table)

	# getting data types
	types = []
	for i in c.fetchone():
		if type(i) == unicode: types.append('S%s' % str_length)
		if type(i) == float: types.append('float')
		if type(i) == int: types.append('int')

	# variable names
	varnm = [i[0] for i in c.description]

	# autodetected dtype
	dtype = zip(varnm,types)
	data = N.fromiter(c, dtype = dtype)

	# closing the connection
	conn.close()

if __name__ == '__main__':
	from timeit import Timer
	import numpy as N
	import os, cPickle, sqlite3

	# making a directory to store simulate data
	if not os.path.exists('./data'): os.mkdir('./data')

	# creating simulated data and variable labels
	varnm = ['id','a','b','c','d','e','f','g','h','i','j']			# variable labels
	nobs = 500000
	data1 =	N.random.randn(nobs,5)	
	data2 =	N.random.randint(-100, high = 100, size = (nobs,5))		

	# adding a string variable
	id = [('id'+str(i)) for i in range(nobs)]

	data1 = [i for i in data1.T]
	data2 = [i for i in data2.T]

	d = []
	d.append(N.array(id))
	d.extend(data1)
	d.extend(data2)

	descr = [(varnm[i],d[i].dtype) for i in xrange(len(varnm))]
	data = N.rec.fromarrays(d, dtype=descr)

	n = 20
	fname = './data/data'

	# testing pickle
	t1 = Timer('test_pickle_save(\"%s\")' % fname, 'from __main__ import test_pickle_save')
	print "\n\nTest saving recarray using cPickle\n"
	print "%.6f sec/pass" % (t1.timeit(number=n)/n)

	# testing sqlite
	t2 = Timer('test_save_sqlite(\"%s\")' % fname, 'from __main__ import test_save_sqlite')
	print "\n\nTest saving recarray with sqlite\n"
	print "%.6f sec/pass" % (t2.timeit(number=n)/n)

	# testing pickle
	t3 = Timer('test_pickle_load(\"%s\")' % fname, 'from __main__ import test_pickle_load')
	print "\n\nTest loading recarray using cPickle\n"
	print "%.6f sec/pass" % (t3.timeit(number=n)/n)

	# testing sqlite
	t4 = Timer('test_load_sqlite(\"%s\")' % fname, 'from __main__ import test_load_sqlite')
	print "\n\nTest loading recarray with sqlite\n"
	print "%.6f sec/pass" % (t4.timeit(number=n)/n)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.