我已经注意到了django调试工具栏,每个django管理列表页面,总是在我的所有查询中添加“ORDER BY id DESC”,即使我手动覆盖admin.ModelAdmin的get_queryset方法(我通常也是这样)因为我想在我的一些管理页面上进行自定义排序)
我想这不是什么值得担心的问题,但这是数据库需要做的额外排序操作,即使它根本没有意义。
有什么方法可以阻止这种情况吗?似乎在某些模型上(即使不是全部)如果我添加了排序元数据,那么它不会自动按ID添加顺序,但是它会添加到该字段,这也是我不喜欢的东西不想要,因为这样做会将该订单添加到代码中的所有其他查询中。
编辑:似乎罪魁祸首是在ChangeList的django.contrib.admin.views.main,在第316行的函数get_ordering上(django 1.7.10)
pk_name = self.lookup_opts.pk.name
if not (set(ordering) & set(['pk', '-pk', pk_name, '-' + pk_name])):
# The two sets do not intersect, meaning the pk isn't present. So
# we add it.
ordering.append('-pk')
我想知道这背后的原因是什么......
编辑: 为了提高性能,并且由于MySQL(和InnoDB)在没有给出order by时以聚簇索引顺序返回数据,我可以安全地删除该id附加。 要做到这一点,这很容易,我刚刚扩展了django的ChangeList并修改了get_ordering方法。之后,只需创建一个自定义的管理模型,该模型从ModelAdmin扩展并覆盖get_changelist方法以重新转换上述类。
我希望它可以帮助任何人:)
答案 0 :(得分:2)
与此问题完全相同的问题是,当我已经拥有唯一排序时,由于ID排序,管理查询集慢了4倍。感谢@ user1777914和他的工作,我没有其他所有负载的超时!我只是在这里添加这个答案是为了清楚,如果其他人遭受同样的痛苦用户1777914提到扩展ChangeList:
class NoPkChangeList(ChangeList):
def get_ordering(self, request, queryset):
"""
Returns the list of ordering fields for the change list.
First we check the get_ordering() method in model admin, then we check
the object's default ordering. Then, any manually-specified ordering
from the query string overrides anything. Finally, WE REMOVE the primary
key ordering field.
"""
params = self.params
ordering = list(self.model_admin.get_ordering(request) or self._get_default_ordering())
if ORDER_VAR in params:
# Clear ordering and used params
ordering = []
order_params = params[ORDER_VAR].split('.')
for p in order_params:
try:
none, pfx, idx = p.rpartition('-')
field_name = self.list_display[int(idx)]
order_field = self.get_ordering_field(field_name)
if not order_field:
continue # No 'admin_order_field', skip it
# reverse order if order_field has already "-" as prefix
if order_field.startswith('-') and pfx == "-":
ordering.append(order_field[1:])
else:
ordering.append(pfx + order_field)
except (IndexError, ValueError):
continue # Invalid ordering specified, skip it.
# Add the given query's ordering fields, if any.
ordering.extend(queryset.query.order_by)
# Ensure that the primary key is systematically present in the list of
# ordering fields so we can guarantee a deterministic order across all
# database backends.
# pk_name = self.lookup_opts.pk.name
# if not (set(ordering) & {'pk', '-pk', pk_name, '-' + pk_name}):
# # The two sets do not intersect, meaning the pk isn't present. So
# # we add it.
# ordering.append('-pk')
return ordering
然后在你的ModelAdmin中覆盖get_changelist:
class MyAdmin(ModelAdmin):
def get_changelist(self, request, **kwargs):
return NoPkChangeList
答案 1 :(得分:0)
7Wonders的答案可以简化为以下语句,因为只需更改ChangeList._get_deterministic_ordering()
:
# admin.py
class MyAdmin(ModelAdmin):
def get_changelist(self, request, **kwargs):
"""Improve changelist query speed by disabling deterministic ordering.
Please be aware that this might disturb pagination.
"""
from django.contrib.admin.views.main import ChangeList
class NoDeterministicOrderChangeList(ChangeList):
def _get_deterministic_ordering(self, ordering):
return ordering
return NoDeterministicOrderChangeList