Django 官方文档同时支持 MySQL 和 PostgreSQL,但在实际工程落地中,两者性能表现高度依赖业务场景与配置优化。PostgreSQL 在复杂查询、并发控制及 JSON 字段支持上更贴合 Django 设计哲学,MySQL 8.0 则适合已有成熟运维体系或读多写少的场景。不存在绝对的性能胜负,建议通过实测数据决策。
先说结论:选型应优先匹配团队技术栈和业务字段需求,而非盲目追求基准测试数据。
- 适合:读多写少且团队熟悉 MySQL 运维的业务可考虑 MySQL。
- 重点看:JSONField 等高级字段在 PostgreSQL 上支持更原生,查询效率更高。
- 别忽略:数据库字符集配置错误会导致中文乱码或索引失效。
- 注意:Django ORM 设计不推荐使用存储过程,应避免依赖此特性选型。
环境搭建与版本确认
在对比前,需确保测试环境一致。推荐使用 Docker 快速部署标准版本,避免本地环境差异干扰测试结果。
1. 部署 MySQL 8.0:
docker run `--name` mysql-test -e MYSQL_ROOT_PASSWORD=yourpassword -p 3306:3306 -d mysql:8.0 `--character-set-server`=utf8mb4 `--collation-server`=utf8mb4_unicode_ci2. 部署 PostgreSQL 14:
docker run `--name` pg-test -e POSTGRES_PASSWORD=yourpassword -p 5432:5432 -d postgres:143. 安装 Python 驱动:
pip install mysqlclient psycopg2-binaryDjango 配置实操
在 settings.py 中切换数据库配置,注意字符集与引擎路径的正确性。
MySQL 配置示例:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'yourdb',
'USER': 'root',
'PASSWORD': 'yourpassword',
'HOST': '127.0.0.1',
'PORT': '3306',
'OPTIONS': {
'charset': 'utf8mb4',
'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
},
}
}PostgreSQL 配置示例:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'yourdb',
'USER': 'postgres',
'PASSWORD': 'yourpassword',
'HOST': '127.0.0.1',
'PORT': '5432',
}
}性能测试方法与数据记录
不要仅依赖理论分析,建议使用 Locust 模拟真实业务流量。以下是一个简单的只读与写入混合测试脚本示例。
locustfile.py 示例:
from locust import HttpUser, task, between
class DBUser(HttpUser):
wait_time = between(1, 3)
@task(3)
def read_data(self):
self.client.get("/api/data/")
@task(1)
def write_data(self):
self.client.post("/api/data/", json={"value": 1})启动测试命令:locust -f locustfile.py `--host`=http://127.0.0.1:8000
测试完成后,请记录以下数据以便对比(请勿直接引用网络基准数据,需本地实测):
| 数据库类型 | 并发用户数 | 平均响应时间 (ms) | QPS | 错误率 |
|---|---|---|---|---|
| MySQL 8.0 | 填写实测值 | 填写实测值 | 填写实测值 | 填写实测值 |
| PostgreSQL 14 | 填写实测值 | 填写实测值 | 填写实测值 | 填写实测值 |
验证与排查步骤
配置切换后,需执行以下验证确保系统稳定:
- 迁移检查:运行
python manage.py migrate,确认无 Pending migrations 警告,观察字段类型映射是否有 Warning。 - 连接验证:查看数据库日志,确认无认证失败。MySQL 可执行
SHOW VARIABLES LIKE 'character%';确认字符集为 utf8mb4。 - 功能回归:重点测试涉及事务提交、复杂查询(如 annotate、aggregate)的页面,确保 ORM 生成的 SQL 执行正常。
- 慢查询分析:开启 Django Debug Toolbar 或数据库慢查询日志,对比相同接口在两种数据库下的执行计划(EXPLAIN)。
常见坑与解决方案
- 字符集问题:MySQL 务必使用 utf8mb4,旧版 utf8 不支持完整 Unicode(如 emoji),会导致保存报错或乱码。
- 自增主键差异:MySQL 使用 AUTO_INCREMENT,PostgreSQL 使用 SEQUENCE。迁移数据时需注意序列重置,否则可能导致主键冲突。
- 事务隔离级别:默认隔离级别不同(MySQL 多为 Repeatable Read,PG 为 Read Committed),高并发测试下可能观察到不一致现象,需根据业务调整。
- JSONField 查询:虽然 Django ORM 做了适配,但 MySQL 的 JSON 查询语法与 PG 不完全相同,复杂查询建议先在测试环境验证生成的 SQL。
- 存储过程误区:Django 社区最佳实践是逻辑层在 Python 代码中,避免依赖数据库存储过程,否则会增加迁移和维护成本。
参考来源
- Django 官方文档 - Database installations: https://docs.djangoproject.com/en/stable/ref/databases/
- Locust 官方文档:https://docs.locust.io/