使用sqlite3与自定义表实现的利弊
我注意到我写的(纯Python)代码中,有很大一部分是在处理表格。当然,我有一个class Table
来支持基本功能,但我发现我不断地给它添加更多的功能,比如查询、验证、排序、索引等等。
我在想,是否应该去掉我的class Table
,改为使用一个普通的关系数据库,而且这个数据库会在内存中运行。
这是我目前的想法:
使用数据库进行查询和索引的性能会更好,但Python代码和单独的数据库进程之间的通信可能没有Python函数之间的效率高。我觉得这样会增加很多开销,所以我可能需要使用Python自带的sqlite,这样它就可以在同一个进程中运行。我希望这意味着性能会有纯粹的提升(虽然sqlite的SQL定义不标准,功能也有限)。
使用SQL,我可以获得很多比我自己编码要强大的功能。这似乎是一个明显的优势(即使是使用sqlite)。
我不需要调试自己实现的表格,但调试SQL中的错误会很困难,因为我不能设置断点或者轻松打印出中间状态。我不知道这对我的代码可靠性和调试时间的整体影响如何评估。
代码会更容易阅读,因为我不再调用自己定义的方法,而是直接写SQL(所有需要维护这段代码的人都懂SQL)。不过,处理数据库的Python代码可能会比使用纯Python的
class Table
更复杂和难看。再次强调,我不确定哪种方式更好。
对以上内容有什么修改建议,或者还有其他我应该考虑的事情吗?
3 个回答
如果你在做数据库相关的工作,那就用数据库;如果不是,那就别用。听起来你在用表格,所以我建议你使用一个ORM,这样会让你的代码更符合Python的风格。SQLAlchemy是最灵活的选择(不过它不仅仅是一个ORM)。
你可以试着做一个sqlite的封装,跟你的Table类的接口保持一致。这样一来,你的代码就会保持整洁,同时还能享受到sqlite的高性能。
SQLite不是在单独的进程中运行,所以你不会遇到额外的进程间通信(IPC)开销。不过,实际上IPC的开销也不大,尤其是用UNIX套接字的时候。如果你需要多个写入者(也就是多个进程或线程同时写入数据库),那么锁定的开销可能会更大,这时候MySQL或PostgreSQL的表现会更好,特别是在同一台机器上运行时。这三种数据库支持的基本SQL是一样的,所以进行性能测试也不会太麻烦。
在调试SQL语句时,通常不需要像调试自己写的代码那样费劲。SQLite本身运行得很好,调试也相对成熟。你几乎不需要调试“好吧,那一行确实存在,为什么数据库找不到它?”这种情况,也不需要追踪索引更新中的错误。调试SQL和调试过程代码是完全不同的,通常只有在处理比较复杂的查询时才会出现问题。
至于调试你的代码,你可以很容易地集中管理你的SQL调用,并添加跟踪功能来记录你运行的查询、得到的结果等等。Python的SQLite接口可能已经有这个功能(我不太确定,我通常用Perl)。最简单的方法可能是把你现有的表类做成SQLite的一个包装。
我强烈建议不要重复造轮子。使用SQLite会有更少的错误,并且能节省你很多时间。(你也可以看看Firefox最近转向使用SQLite来存储历史记录等,他们从中获得了显著的速度提升。)
另外,SQLite用C语言实现得非常优化,速度可能比任何纯Python的实现都要快得多。