当前位置: 代码网 > it编程>前端脚本>Python > 浅谈django的db性能调优

浅谈django的db性能调优

2026年02月04日 Python 我要评论
1 环境准备构建一个user_demo表from django.db import modelsclass userinfo(models.model): # 1. 基础字段 userna

1 环境准备

构建一个user_demo表

from django.db import models

class userinfo(models.model):
    # 1. 基础字段
    username = models.charfield(max_length=50, unique=true)
    # 给 email 一个默认空字符串,或者设为 null=true,防止迁移报错
    email = models.emailfield(default='') 

    # 2. 状态字段
    status = models.smallintegerfield(default=1, help_text="0:inactive, 1:active, 2:banned")
    role = models.charfield(max_length=10, default='member')

    # 3. 数值字段
    age = models.positivesmallintegerfield(null=true)
    balance = models.decimalfield(max_digits=19, decimal_places=4, default=0.0000)
    score = models.integerfield(default=0)

    # 4. 时间字段
    # 使用 auto_now_add=true 让 django 自动处理创建时间
    created_at = models.datetimefield(auto_now_add=true) 
    last_login = models.datetimefield(null=true, blank=true)

    # 5. 大文本/复杂字段
    bio = models.textfield(null=true, blank=true)
    
    # 6. json 字段
    extras = models.jsonfield(default=dict, null=true, blank=true)

    class meta:
        db_table = 'user_demo'

迁移

python manage.py makemigration
python manage.py migrate

2 创建调优

使用bulk_create创建1万条数据

import os
import sys
import random
import string
import django

# 1. 设置 django 环境
base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(base_dir)
os.environ.setdefault("django_settings_module", "mysite.settings")
django.setup()

from main.models import userinfo

def generate_random_string(length=10):
    """生成随机字符串"""
    letters = string.ascii_lowercase
    return ''.join(random.choice(letters) for i in range(length))

def create_demo_data(count=100):
    print(f"开始生成 {count} 条数据...")
    
    users = []
    # 预先定义好 choices,模拟真实数据分布
    roles = ['admin', 'editor', 'member', 'guest']
    
    for i in range(count):
        # 确保 username 唯一,这里简单加上索引 i
        username = f"user_{generate_random_string(5)}_{i}"
        
        user = userinfo(
            username=username,
            email=f"{username}@example.com",
            status=random.choice([0, 1, 1, 1, 2]), # 1 的概率大一些
            role=random.choice(roles),
            age=random.randint(18, 80),
            balance=random.uniform(0, 100000),
            score=random.randint(0, 500000),
            bio=generate_random_string(500),
            extras={'preference': random.choice(['light', 'dark']), 'level': random.randint(1, 10)}
        )
        users.append(user)

    # bulk_create 一次性插入,性能更好
    userinfo.objects.bulk_create(users)
    print(f"✅ 成功插入 {len(users)} 条数据到 userinfo 表。")

if __name__ == "__main__":
    try:
        create_demo_data(1000000)
    except exception as e:
        print(f"❌ 发生错误: {e}")

创建成功

mysql> select count(*) from user_demo;
+----------+
| count(*) |
+----------+
|    10000 |
+----------+
1 row in set (0.002 sec)

构建10万条失败,失败信息为:

开始生成 1000000 条数据...
❌ 发生错误: (2013, 'lost connection to mysql server during query')

采取分批插入的方式来解决问题

import os
import sys
import random
import string
import django

# 1. 设置 django 环境
base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(base_dir)
os.environ.setdefault("django_settings_module", "mysite.settings")
django.setup()

from main.models import userinfo

def generate_random_string(length=10):
    """生成随机字符串"""
    letters = string.ascii_lowercase
    return ''.join(random.choice(letters) for i in range(length))

def create_demo_data(count=100):
    print(f"开始生成 {count} 条数据...")
    
    users = []
    batch_size = 5000  # 每次插入 5000 条
    # 预先定义好 choices,模拟真实数据分布
    roles = ['admin', 'editor', 'member', 'guest']
    batch_data = []
    for i in range(count):
        # 确保 username 唯一,这里简单加上索引 i
        username = f"user_{generate_random_string(5)}_{i}"
        
        user = userinfo(
            username=username,
            email=f"{username}@example.com",
            status=random.choice([0, 1, 1, 1, 2]), # 1 的概率大一些
            role=random.choice(roles),
            age=random.randint(18, 80),
            balance=random.uniform(0, 100000),
            score=random.randint(0, 500000),
            bio=generate_random_string(500),
            extras={'preference': random.choice(['light', 'dark']), 'level': random.randint(1, 10)}
        )

        batch_data.append(user)
        # 当积攒够了 batch_size,就插入一次
        if len(batch_data) >= batch_size:
            userinfo.objects.bulk_create(batch_data, batch_size=batch_size)
            print(f"已插入 {i + 1} 条...")
            batch_data = [] # 清空列表

    # 插入剩余的数据(如果有的话)
    if batch_data:
        userinfo.objects.bulk_create(batch_data)
        print(f"已插入剩余 {len(batch_data)} 条...")
    print(f"✅ 成功插入 {len(users)} 条数据到 userinfo 表。")

if __name__ == "__main__":
    try:
        create_demo_data(1000000)
    except exception as e:
        print(f"❌ 发生错误: {e}")

3 查找优化

这种查找,性能非常操作,因为本质上是在做:select * from table ...

from main.models import userinfo

users = userinfo.objects.all()
users_usernames = [user.username for user in users]

改成

from main.models import userinfo

users_usernames = list(userinfo.objects.values_list('username', flat=true))

到此这篇关于浅谈django的db性能调优的文章就介绍到这了,更多相关django db性能调优内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com