如何给服务器上已创建的MySQL数据库添加索引?Django查询优化
解决Django+MySQL关联查询慢的问题
先直接给你明确答案,再一步步拆解细节:
一、该给哪个字段加索引?
你需要在**Product表的外键字段(Django默认命名为another_id)**上创建索引。原因很简单:
- 你的查询
Product.objects.filter(another__id='x')本质是让MySQL找到所有another_id等于x的Product记录,给这个外键字段加索引,能让数据库快速定位到符合条件的行,避免全表扫描100万条数据。 - 而another表的
id本身是主键,MySQL默认会给主键创建唯一索引,所以不用再给它额外加索引了。
二、正确的索引创建方式
你写的CREATE INDEX "another" ON Product是错误的,因为没有指定具体关联字段。推荐两种靠谱的方式:
方式1:用Django迁移系统(更安全,符合Django最佳实践)
在models.py里给Product模型的外键字段加上db_index=True:
class Product(models.Model): another = models.ForeignKey(AnotherModel, on_delete=models.CASCADE, db_index=True) # 其他字段...
然后在终端执行迁移命令:
python manage.py makemigrations python manage.py migrate
Django会自动帮你生成正确的索引,不用担心字段名写错(比如它默认会把外键存储为another_id字段)。
方式2:手动执行SQL语句
如果直接操作数据库,正确的SQL是:
CREATE INDEX idx_product_another_id ON Product(another_id);
这里idx_product_another_id是自定义的索引名(语义清晰就行),another_id是Product表中实际存储外键值的字段。
三、执行索引创建时的锁问题
对于现在MySQL默认的InnoDB存储引擎:
- 如果你用的是MySQL 5.6及以上版本,
CREATE INDEX或ALTER TABLE ADD INDEX属于Online DDL操作,执行过程中只会在最后阶段有极短时间的锁,大部分时间允许对Product表进行读写,不会长时间阻塞业务。 - 如果是MySQL 5.5及更早版本,创建索引会锁表,建议在业务低峰期执行,避免影响正常服务。
额外提醒:创建索引后可以用EXPLAIN验证是否生效:
EXPLAIN SELECT * FROM Product WHERE another_id = 'x';
如果type列显示ref或range,说明索引已经在工作,查询速度会大幅提升。
内容的提问来源于stack exchange,提问作者user10421193
相关产品推荐
相关产品推荐

