Django order_by 导致 LEFT JOIN
Posted
技术标签:
【中文标题】Django order_by 导致 LEFT JOIN【英文标题】:Django order_by causes LEFT JOIN 【发布时间】:2011-08-22 01:27:16 【问题描述】:谁能告诉我为什么当我添加order_by()
时,获取输出的查询会从INNER JOIN
更改为LEFT OUTER JOIN
?
有什么办法可以保留INNER JOIN
-ness?
data = models.RetailSalesFact.objects.values('customer_key__customer_state',
'date_key__calendar_month_name')
data = data.filter(date_key__calendar_year=year)
data = data.annotate(sales=Sum('sales_quantity'))
data = data.order_by('date_key__calendar_month_name')
之前:
SELECT Customer_Dimension.Customer_State, Date_Dimension.Calendar_Month_Name,
SUM(Retail_Sales_Fact.Sales_Quantity) AS sales
FROM Retail_Sales_Fact
INNER JOIN Customer_Dimension
ON (Retail_Sales_Fact.Customer_Key = Customer_Dimension.Customer_Key)
INNER JOIN Date_Dimension
ON (Retail_Sales_Fact.Date_Key = Date_Dimension.Date_Key)
WHERE Date_Dimension.Calendar_Year = ?
GROUP BY Customer_Dimension.Customer_State,
Date_Dimension.Calendar_Month_Name
ORDER BY Date_Dimension.Calendar_Month_Name ASC
之后:
SELECT Customer_Dimension.Customer_State, Date_Dimension.Calendar_Month_Name,
SUM(Retail_Sales_Fact.Sales_Quantity) AS sales
FROM Retail_Sales_Fact
INNER JOIN Customer_Dimension
ON (Retail_Sales_Fact.Customer_Key = Customer_Dimension.Customer_Key)
LEFT OUTER JOIN Date_Dimension
ON (Retail_Sales_Fact.Date_Key = Date_Dimension.Date_Key)
WHERE Date_Dimension.Calendar_Year = ?
GROUP BY Customer_Dimension.Customer_State,
Date_Dimension.Calendar_Month_Name
ORDER BY Date_Dimension.Calendar_Month_Name ASC
【问题讨论】:
【参考方案1】:我猜 ORM 正在执行 LEFT JOIN
,因为它无法判断 INNER JOIN
的 where 限制是否比排序子句更具限制性。因为它认为它需要对每条记录进行排序,无论它是否匹配。
您可以使用Raw SQL 强制INNER JOIN
。或者您可以通过在filter
之前应用order_by
来欺骗ORM?
【讨论】:
【参考方案2】:您在外部表上放置了一个过滤器 (date_dimension__calendar_year=year),因此无论您使用内连接还是左外连接,结果集之间都没有区别。
order-by 是在中间结果集上处理的——如果在内部连接的表上完成,那么它必须在组合表之后完成——这意味着读取一个:组合记录;阅读二:排序合并记录。
但是,如果仅在外连接表上完成排序,在这种情况下,这就是您所要求的,那么您的查询优化器可能能够避免读取整个集合两次,而是,只读取了外部表两次。您的优化器可能会认为这是在处理能力方面的节省。
这只是一个猜测。无论哪种方式,您的结果集都应该是相同的。我想知道你是否可以两种方式都计时,看看哪一种需要更长的时间。
【讨论】:
结果集是相同的,但是 INNER JOIN 和 LEFT JOIN 之间的时间相当重要。它可能不会对相对较小的数据集造成任何损害,但随着表格填满,它会产生很大的影响。 所以inner-join + order-by比left-outer-join + order-by花费的时间更少?我以为您最初是在比较内部连接(没有排序依据)。 尝试重新排序您的 Group-by 声明。您的数据集实际上被排序了两次——首先按 Group-by,然后按 order-by。把group-by改成这个:GROUP BY Date_Dimension.Calendar_Month_Name,Customer_Dimension.Customer_State,然后去掉order-by子句,能不能得到你想要的结果?以上是关于Django order_by 导致 LEFT JOIN的主要内容,如果未能解决你的问题,请参考以下文章
DJANGO:如何使用包含 order_by 的模型创建管理视图?
080:Django数据库QuerySet API详解-order_by: