Which database is faster? The highly optimised SQLAlchemy library, or the library that literally saves and loads the entire csv every time you modify it?
data = {'name': ['Sam', 'Grant'],
'mood': ['😊', '😵'],
'message': ['hello from London, UK', 'hello from Christchurch, NZ'],
'time_utc' : [utc_now(), utc_now()]}
# ================================================================ #
Duration to insert, append, save, and reload the dataframe 100 times.
%%time
def test_prodb(n=1, verbose=True):
dbpath='benchmarks/prodb.csv'
df = generate_db(dbpath=dbpath, cols='name mood message'.split(), verbose=verbose)
for i in range(n):
df = insert_rows(df, data, dbpath=dbpath) # save to disk
df = pd.read_csv(dbpath) # load from disk
return df
df = test_prodb(n=100)
print(df.shape)
display(df.tail())
df.shape
%%timeit
df.to_csv('benchmarks/tmp.csv')
%%timeit
df = pd.read_csv('benchmarks/tmp.csv')
%%timeit
df.iloc[50, :]
2. SQLModel / SQLAlchemy Benchmarks
SQLModel code and functions from lukexyz/sqlmodel-streamlit/app.py
from sqlmodel import Field, Session, SQLModel, create_engine, select
from typing import Optional
import logging, sys
logging.disable(sys.maxsize)
class Hero(SQLModel, table=True):
__table_args__ = {'extend_existing': True} # required for streamlit refreshing
id: Optional[int] = Field(default=None, primary_key=True)
name: str
secret_name: str
age: Optional[int] = None
def create_db_and_tables():
SQLModel.metadata.create_all(engine)
def get_table():
with Session(engine) as session:
heroes = session.exec(select(Hero)).all()
return pd.DataFrame([s.dict() for s in heroes])
def delete_db():
with Session(engine) as session:
heroes = session.exec(select(Hero)).all()
for hero in heroes:
session.delete(hero)
session.commit()
def commit_new_row():
hero = Hero(name='Luke', secret_name='Luke Woods', age=23)
hero_1 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=36)
with Session(engine) as session:
session.add(hero)
session.add(hero_1)
session.commit()
sqlite_file_name = 'sqlmodel.db'
sqlite_url = f"sqlite:///{sqlite_file_name}"
engine = create_engine(sqlite_url, echo=True)
delete_db()
create_db_and_tables()
commit_new_row()
get_table()
%%time
delete_db()
create_db_and_tables()
def test_sqlmodel(n=100):
for k in range(n):
commit_new_row() # add two rows to db
return get_table()
df = test_sqlmodel(n=100)
print(df.shape)
df.tail()
SQLAlchemy
- Good code from the good man Jesse Jcharis on github
import pandas as pd
import json
import sqlite3
conn = sqlite3.connect('benchmarks/sqlite.db',check_same_thread=False)
c = conn.cursor()
def create_table():
c.execute('CREATE TABLE IF NOT EXISTS taskstable(name TEXT,mood TEXT,message TEXT)')
def add_data(name,mood,message):
c.execute('INSERT INTO taskstable(name,mood,message) VALUES (?,?,?)',(name,mood,message))
conn.commit()
def view_all_data():
c.execute('SELECT * FROM taskstable')
data = c.fetchall()
return data
def empty_table(name):
c.execute('DELETE FROM taskstable WHERE name="{}"'.format(name))
conn.commit()
create_table()
name = "Luke"
mood = "👍"
message = "An SQLite database entry"
empty_table(name)
add_data(name, mood, message)
ds = pd.DataFrame(view_all_data(), columns=['name', 'mood', 'message'])
print(ds.shape)
ds.tail()
%%time
def test_sqlalchemy(n=100):
for i in range(n):
add_data(name, mood, message)
res = view_all_data()
test_sqlalchemy(n=100)
from tqdm.notebook import tqdm
from utils.timer import Timer
_t = {'prodb': Timer()}
test_range = range(1, 1002, 50)
commits = []
time = []
for i in tqdm(list(test_range)):
_t['prodb'].tic()
dt = test_prodb(n=i, verbose=False)
time.append(1000*round(_t['prodb'].toc(), 4))
commits.append(dt.shape[0])
dx = pd.DataFrame()
dx['commits'] = commits
dx['prodb_ms'] = time
commits = []
time = []
for i in tqdm(list(test_range)):
_t = {'db': Timer()}
_t['db'].tic()
test_sqlmodel(n=i)
time.append(1000*round(_t['db'].toc(), 4))
commits.append(i+1)
dx['sqlmodel_ms'] = time
commits = []
time = []
for i in tqdm(list(test_range)):
_t = {'db': Timer()}
_t['db'].tic()
test_sqlalchemy(n=i)
time.append(1000*round(_t['db'].toc(), 4))
commits.append(i+1)
dx['sqlalchemy_ms'] = time
dx.head()
import matplotlib.pyplot as plt
dx.set_index('commits').plot.line()