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性能调优内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论