我正在使用django 1.8.4编写一个webapp。后端使用MySQL 5.6(MyISAM)。最近表记录的数量达到100万,查询所有不同的记录日期需要1-1.5秒。但是使用MySQL客户端需要不到0.001秒。
Django代码
class Model1(models.Model):
date = models.DateField(db_index=True)
# benchmark code
db_dates = Model1.objects.dates("date", kind="day")
MySQL查询:
SELECT date FROM `table1` group by date ORDER BY `date` ASC
MySQL客户端说:总共620,查询耗时0.0025秒。
关于@ e4c5提示,我转储了django查询。实际上在查询中有一个类型转换。这是缓慢的根本原因。
{u'time': u'1.989',
u'sql': u"SELECT DISTINCT CAST(DATE_FORMAT(`model1_table`.`date`, '%Y-%m-%d 00:00:00') AS DATETIME) AS `datefield` FROM `model1_table` WHERE `model1_table`.`date` IS NOT NULL ORDER BY `datefield` ASC"}
即使我在MySQL客户端中手动运行查询,它也会变慢。我注意到第二个查询进行了类型转换。
类型广告(date
到datetime
)是否必要?我该如何解决这个问题呢?
无论如何,我已经开了issue here用于跟踪。
答案 0 :(得分:2)
Django在内部生成这样的查询:
SELECT DISTINCT
CAST(
DATE_FORMAT(`model1_table`.`date`, '%Y-%m-%d 00:00:00') AS DATETIME
) AS `datefield`
FROM `model1_table` WHERE `model1_table`.`date` IS NOT NULL
ORDER BY `datefield` ASC"
显然,所有DATE字段首先被转换为DATETIME,然后使用其日期部分。性能影响是根据记录数量进行扩展。
results = set(obj.date for obj in Model1.objects.distinct('date'))
但这仅适用于PostgreSQL。它不适用于MySQL。我们将收到错误:“此数据库后端不支持 DISTINCT ON字段”。
distinct
来过滤服务器端的结果。 这是我修改过的版本。
results = set(Model1.objects.order_by('date').values_list('date', flat=True).distinct())
现在只需0.004秒即可查询150万条记录中的不同日期字段。酷!
答案 1 :(得分:1)
由于MySQL在django ORM中不支持DISTINCT ON,你可以在客户端进行:
set(Model1.objects.order_by('date').values_list('date', flat=True))