Django 部署数据库选择 MySQL 8.0 还是 PostgreSQL 14 性能对比?

文章导读
Django 官方文档同时支持 MySQL 和 PostgreSQL,但在实际工程落地中,两者性能表现高度依赖业务场景与配置优化。PostgreSQL 在复杂查询、并发控制及 JSON 字段支持上更贴合 Django 设计哲学,MySQL 8.0 则适合已有成熟运维体系或读多写少的场景。不存在绝对的性能胜负,建议通过实测数据决策。
📋 目录
  1. 环境搭建与版本确认
  2. Django 配置实操
  3. 性能测试方法与数据记录
  4. 验证与排查步骤
  5. 常见坑与解决方案
  6. 参考来源
A A

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_ci

2. 部署 PostgreSQL 14:

Django 部署数据库选择 MySQL 8.0 还是 PostgreSQL 14 性能对比?
docker run `--name` pg-test -e POSTGRES_PASSWORD=yourpassword -p 5432:5432 -d postgres:14

3. 安装 Python 驱动:

pip install mysqlclient psycopg2-binary

Django 配置实操

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 模拟真实业务流量。以下是一个简单的只读与写入混合测试脚本示例。

Django 部署数据库选择 MySQL 8.0 还是 PostgreSQL 14 性能对比?

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填写实测值填写实测值填写实测值填写实测值

验证与排查步骤

配置切换后,需执行以下验证确保系统稳定:

  1. 迁移检查:运行 python manage.py migrate,确认无 Pending migrations 警告,观察字段类型映射是否有 Warning。
  2. 连接验证:查看数据库日志,确认无认证失败。MySQL 可执行 SHOW VARIABLES LIKE 'character%'; 确认字符集为 utf8mb4。
  3. 功能回归:重点测试涉及事务提交、复杂查询(如 annotate、aggregate)的页面,确保 ORM 生成的 SQL 执行正常。
  4. 慢查询分析:开启 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/