Django 对 Sqlite、Mysql、Postgresql 三种数据库支持小结
三种数据库各有优劣,需要根据自己的情况来选择。比如 Sqlite 不支持并发,那显然不能用来作为大型网站的数据库,而 Mysql 在 Django 3.1 版本之前并不支持 JSONField,如果 JSONField 必须要用到那肯定也是不能选的,而 Postgresql 特性齐全,但是往往用的人比较少,难以获得足够的资料。
因此,在这里记录一下各个数据库的注意事项,方便以后的选择。等等!官方不还支持 Oracle 数据库吗,怎么没说?这数据库我真没用过,而且可见的将来都用不到,目前就不管了。
Sqlite
Sqlite 无法并发写入,但是能并发读取,因此适合用作读多写(并发写入)少的场景,更常见的用处是用作开发用的测试数据库。当然有时候无法完全模拟生产环境,还是会换到其他数据库的。主要有以下特点:
- 数据库字串的匹配不区分大小写,像
filter(name__contains="aa")
这样的子句会匹配到 "Aabb"。 - 含有 ASCII 码以外字符的字符串匹配一定区分大小写,即使你传入了不区分大小写参数。
- Sqlite 内部没有小数类型,因此小数的舍入会有问题。
- 不支持
SELECT ... FOR UPDATE
语法 - 使用原始查询时不支持参数以字典形式传入并用
'%(name)s'
格式化,必须传入以列表形式传入。 - 使用
QuerySet
迭代查询结果并修改时,会进入薛定谔的数据库状态,Sqlite 无法保证会发生什么,可能成功也可能失败,取决于数据库版本、运行时的状态等,无法预期确定的结果。 - 支持 JSONField,但 Python 自带的 Sqlite 库需要启用 JSON1 扩展。
Mysql
对于 Mysql 有个同源的发行版 MariaDB,目前 Django 支持 MariaDB 仅支持 10.2 及以上版本。并非是因为之前版本有什么兼容性问题,主要是由于上游对于 10.2 之前版本的安全更新支持到期了,所以 Django 也就放弃支持了,需要的话酌情使用。而 Mysql 的话支持 5.6 及以上版本,5.7 和 5.6 的新版本可以开启严格模式,有更好的事务隔离性。
Mysql 旧版本一直是使用 MyISAM 储存引擎,它的缺点应该广为人知了,不支持事务和也不执行外键约束。而使用 InnoDB 就没有这两个问题了,但是需要注意 InnoDB 的自动增量计数器在 MySQL 重启时会丢失,直到 Mysql 8.0 才修复。Django 生成数据库架构的时候没有设置储存引擎,如果数据库默认配置不正确,需要手动设置为 InnoDB。此外,开启时区后,Django 会在数据库中创建一个 mysql_tzinfo_to_sql
表。
Mysql 还有要特别注意的是创建数据库时要使用 utf-8
字符集,同时字符序默认为 utf8_general_ci
,比 utf8_unicode_ci
更快,但准确率略低(如德语字典顺序不对),并且数据库不区分大小写。另外,当在某些条件下执行某些 SQL 语句时,可能会导致表名的大小写被改变,建议使用全小写的表名以避免发生问题。其他的主要特点有:
- Django 推荐使用比 Mysql 默认更高的隔离级别,否则
get_or_create()
可能会引发一个IntegrityError
。 - Django 生成数据库架构的时候没有设置储存引擎,如果数据库默认配置不正确,需要手动设置为 InnoDB。
- MyISAM 储存引擎不支持保存点。
- 如果
varchar
字段使用了unique=True
,max_length
可能被限制在 255 个字符 - 只能对 BLOB 或 TEXT 列的前 N 个字符进行索引,并且 TextField 没有定义的长度,所以不能用 unique=True。
- 5.6.4 后支持小数秒,但是必须在列定义中包含(例如 DATETIME(6))。
- inspectdb 导出模型包含 TIMESTAMP 列的旧数据库时,必须设置 USE_TZ = False
SELECT ... FOR UPDATE
的某些选项不支持,同时select_for_update()
过滤时必须选择有唯一约束或索引的列,否则这个操作会独占整个表的写入锁。- 对字符串字段进行证书查询时,Django 会把数字转为字符串,否则有奇怪的结果。
Postgresql
Django 支持 Postgresql 9.5 及以上版本,同时 Django 对 Postgresql 的支持几乎是最好的,这很大程度上由于 Postgresql 的先进性和规范性,结果就是你在 Django 上使用 Postgresql 时几乎不会遇到什么离奇的问题,官方文档中几乎没有什么关于 Postgresql 需要特别注意的事项。
而且 Postgresql 的 jsonb
、postgis
等各种独有索引和数据类型支持绝对的功能强大。除了对 Postgresql 不熟,中文资料较少外,没什么劣势,有条件必然是选择 Postgresql。
总结
看情况,保证自己能解决遇到的问题,爱用什么用什么,当然对于个人使用 Django 必然首推 Postgresql。