我在为查询构建正确索引时遇到问题 我有这样的模型:
from django.db import models
class Record(models.Model):
user = models.ForeignKey(User, db_index=True, related_name='records')
action = models.ForeignKey(Action, db_index=True)
time = models.DateTimeField(db_index=True, default=timezone.now)
class Meta:
index_together = (
('user', 'time'),
('action', 'user', 'time'),
)
如您所见,此模型有两个自定义索引。
如果我想获取与time
过滤的特定用户相关的所有记录,我会使用此查询:user.records.filter(time__gt=some_moment)
。它工作正常并使用第一个自定义索引(根据Django Debug Toolbar)。
现在,在我的情况下,结果必须按action
排序。我使用此查询:user.records.filter(time__gt=some_moment).order_by('action')
。
但是,尽管存在适当的索引,但不使用它。
我做错了什么?如何为此查询构建正确的索引?
Django版本= 1.8.4,应用了所有迁移,数据库后端= mysql。
UPD:有我的疑问:
SELECT *** FROM `appname_record`
WHERE (`appname_record`.`user_id` = 1896158 AND
`appname_record`.`time` > '2015-10-19 06:39:30.992790')
ORDER BY `appname_record`.`action_id` ASC
有完整的django工具栏说明:
ID: 1
SELECT_TYPE: SIMPLE
TABLE: appname_record
TYPE: ALL
POSSIBLE_KEYS:
appname_record_user_id_3214bab8a46891cc_idx, appname_record_07cc694b
KEY: None
KEY_LEN: None
REF: None
ROWS: 240
EXTRA: Using where; Using filesort
有关键的mysql show create table appname_record;
部分:
PRIMARY KEY (`id`),
KEY `appname_record_action_id_3e42ba1d5288899c_idx` (`action_id`, `user_id`,`time`),
KEY `appname_record_user_id_3214bab8a46891cc_idx` (`user_id`,`time`),
KEY `appname_record_07cc694b` (`time`),
所以看起来正确的指数即使在可能的键中也是如此。
答案 0 :(得分:5)
如果查询根本不使用任何索引,那通常是因为表中没有足够的数据使索引真正有用。然而,有500条记录,指数很有可能发挥作用。
在您使用的查询中,appname_record_user_id_3214bab8a46891cc_idx
确实可能是候选人,但仍未使用。为什么?因为你的查询显然会导致数据库看到大约一半的表,因为这样的索引无法加快速度。
你似乎在放弃一个索引的正确轨道上。两个很多类似的索引也不是很有用。我会尝试这个索引:
class Meta:
index_together = (
('user', 'time','action'),
)
这里的区别在于字段的顺序。这是important:
MySQL可以对测试所有内容的查询使用多列索引 索引中的列,或仅测试第一列的查询, 前两列,前三列,依此类推。如果你指定 索引定义中的列顺序正确,单个 复合索引可以加快几种查询的速度 表
答案 1 :(得分:4)
我找到了解决方案,它并不优雅,但它对我有用。由于我无法构建任何将使用3列索引的查询,因此我jush删除了2列,因此现在我的两个查询都使用3列。不知道为什么之前被忽略了。也许,一些复杂的mysql优化。
答案 2 :(得分:0)
对于新版本的Django,建议在Index_togather元选项上使用Index。
https://docs.djangoproject.com/en/2.2/ref/models/options/#unique-together https://docs.djangoproject.com/en/2.2/ref/models/options/#index-together