Django:向 Django 过滤器添加额外的 BooleanField 或 (SQL tinyint) 后,ORM/SQL 查询速度显着降低

Django: ORM/SQL query speed significantly decreased after adding additional BooleanField or (SQL tinyint) to Django Filter

使用 MySQL 最新的 Django:

我有一个运行速度相当快的模糊复杂的 Django 查询——直到我添加一个带有布尔字段的附加 "AND"—— 见下文:

queriedForms = queryFormtype.form_set.filter(is_public=True) 
newQuery = queriedForms.filter(formrecordattributevalue__record_value__icontains=term['TVAL'], formrecordattributevalue__record_attribute_type__pk=rtypePK)
newQuery = newQuery.filter(flagged_for_deletion=False)
logger.info(newQuery.query)
term['count'] =  newQuery.count()

如果我删除初始的 "is_public=True" 或最终的“flagged_for_deletion=False)——它的工作速度非常快。如果我将两者都用作过滤器,它会增加计数的时间( ) 功能类似于 2000%

不同的 QuerySet.query 输出如下:

SELECT `maqluengine_form`.`id`, `maqluengine_form`.`form_name`, `maqluengine_form`.`form_number`, `maqluengine_form`.`form_geojson_string`, `maqluengine_form`.`hierarchy_parent_id`, `maqluengine_form`.`is_public`, `maqluengine_form`.`project_id`, `maqluengine_form`.`date_created`, `maqluengine_form`.`created_by_id`, `maqluengine_form`.`date_last_modified`, `maqluengine_form`.`modified_by_id`, `maqluengine_form`.`sort_index`, `maqluengine_form`.`form_type_id`, `maqluengine_form`.`flagged_for_deletion` FROM `maqluengine_form` INNER JOIN `maqluengine_formrecordattributevalue` ON (`maqluengine_form`.`id` = `maqluengine_formrecordattributevalue`.`form_parent_id`) WHERE (`maqluengine_form`.`form_type_id` = 319 AND `maqluengine_form`.`is_public` = True AND `maqluengine_formrecordattributevalue`.`record_value` LIKE %seal% AND `maqluengine_formrecordattributevalue`.`record_attribute_type_id` = 18510 AND `maqluengine_form`.`flagged_for_deletion` = False)
SELECT `maqluengine_form`.`id`, `maqluengine_form`.`form_name`, `maqluengine_form`.`form_number`, `maqluengine_form`.`form_geojson_string`, `maqluengine_form`.`hierarchy_parent_id`, `maqluengine_form`.`is_public`, `maqluengine_form`.`project_id`, `maqluengine_form`.`date_created`, `maqluengine_form`.`created_by_id`, `maqluengine_form`.`date_last_modified`, `maqluengine_form`.`modified_by_id`, `maqluengine_form`.`sort_index`, `maqluengine_form`.`form_type_id`, `maqluengine_form`.`flagged_for_deletion` FROM `maqluengine_form` INNER JOIN `maqluengine_formrecordattributevalue` ON (`maqluengine_form`.`id` = `maqluengine_formrecordattributevalue`.`form_parent_id`) WHERE (`maqluengine_form`.`form_type_id` = 319 AND `maqluengine_form`.`is_public` = True AND `maqluengine_formrecordattributevalue`.`record_value` LIKE %seal% AND `maqluengine_formrecordattributevalue`.`record_attribute_type_id` = 18510)

第一个执行 count() 大约需要 20/30 秒,而第二个只有两个 BooleanField 中的一个执行 count()

======================================= 编辑======================= 抱歉:因为问题不够明显——为什么添加额外的 AND 和 BooleanField 会使查询时间增加 +2000%?是否有人能够协助找出发生这种情况的原因。谢谢

编辑=========================

还发现使用 exclude(is_public=False) 而不是 filter(is_public=True) 与下面的解决方案具有相同的效果。有没有人碰巧知道为什么 exclude() 可以正常工作——而 filter() 却不行?

================================

经过一夜的休息得出的解决方案:

--我保持查询不变(我以后需要它,因为它会继续进行链过滤) --我需要这个阶段的 count()--这比使用额外的 BooleanField 和应该花费的时间要长得多 --我取一个临时值列表来执行 len() 代替:

queriedForms = queryFormtype.form_set.all()
newQuery = queriedForms.filter(formrecordattributevalue__record_value__icontains=term['TVAL'], formrecordattributevalue__record_attribute_type__pk=rtypePK)
newQuery = newQuery.filter(flagged_for_deletion=False)
tempQuery = newQuery.values_list('is_public',flat=True)
finalQuery = [entry for entry in tempQuery if entry != 'False'] #Remove any indices that contain "False"
term['count'] =  len(finalQuery)

以下使用相同技术后使用链式过滤器的计数 - 它明显更快 - 如果不如从过滤器中删除一个布尔值那么快。