我注意到,在Django的遗留版本中,一个曾经很快的查询现在在4.0.8中慢了很多.

有一个相当大的表,带有一个FK‘标记’和一个附加了索引的布尔‘标记’.以下查询可能会合理地返回数万行.

在我的代码库中,有一个查询,如

MyModel.objects.filter(marker_id=123, flag=False).count()

在Django Debug工具栏中(在我判断str(qs.query)的时候,在Shell中也是如此),它现在解析为以下SQL语法:

SELECT ••• FROM `myapp_mymodel` WHERE (`myapp_mymodel`.`marker_id` = 123 AND NOT `myapp_mymodel`.`flag`)

在极端情况下,该查询大约运行20秒.同时,在传统的Django版本(1.11+)中,相同的查询变成以下SQL:

SELECT ••• FROM `myapp_mymodel` WHERE (`myapp_mymodel`.`marker_id` = 123 AND `myapp_mymodel`.`flag` = 0)

这是可行的,因为表模式包含作为TINYINT(1)的‘FLAG’,但最重要的是,它的工作速度提高了much--返回不到一秒.

EDIT:我要求SQL SERVER解释这两个查询,在后一个(较快的)查询中显示为潜在关键字的‘FLAG’有所不同,而在较慢的查询中没有.这与this answer一致,说明MySQL需要查看与某个值的比较才能使用索引.因此,主要问题变成了,我如何强制使用已经存在的索引的语法?

END EDIT

Original questions:Why is the difference in ORM-to-SQL translation, and where can I find the code responsible (I have checked db.backends.mysql to no avail, or failed to recognize the culprit)? Is there a way to hint to Django that I'd much prefer the equals-zero behaviour?

到目前为止,我看到的唯一解决办法是使用原始SQL查询.如果可能的话,我宁愿避免这种情况.

推荐答案

这是Django的问题跟踪器issue #32691中已经报告和解决的回归.

这个问题已经在Django 4.1中修复了,所以如果你更新它,它会自动得到解决.对于版本3.2到4.0,您可以使用Todor Velichkov在该问题上指出的workaround,即使用Value() expressions:

from django.db.models import Value


MyModel.objects.filter(marker_id=123, flag=Value(0)).count()

Mysql相关问答推荐

如何有效地计算共同的朋友/追随者?

MySQL查询基于上次访问时间戳更新用户的问题

错误:数据包顺序错误.GET:0预期:10 node JS MySQL

将上传文件的存储路径放在一张表中的缺点是什么?

根据 MySql 中同一表中的多列 Select 多列

过滤值为0时如何在MySQL查询中设置条件?

从 MySQL 8.0.12 升级到 8.0.32 时出错

如何使用sql查询在日期列中按值和最大值分组的表中添加列?

try 在 .map 中使用 Favorite 选项卡进行react .我无法更改 mysql 表上的布尔类型

为什么 MySQL 不使用索引进行简单的SELECT * FROM Table WHERE field='value'查询?

访问 nodejs、mysql 和 json 中的嵌套对象数组

如何在更新语句中使用多个子字符串函数?

有没有更好的方法在无限滚动的网页上呈现获取的提要数据?

如何在 MySQL 中删除具有 2 列作为复合主键的多行?

PHP,MySQL 错误:列计数与第 1 行的值计数不匹配

MySQL触发器在某些条件下防止INSERT

MySQL计算特定值的列

PHP 判断 NULL

使用 mysqldriver 连接数据库时出错

在 MySQL Workbench 中导出超过 1000 条记录的查询结果