如何在views.py上优化Django SQL SELECT Query?
Posted
技术标签:
【中文标题】如何在views.py上优化Django SQL SELECT Query?【英文标题】:How to optimize Django SQL SELECT Query on views.py? 【发布时间】:2013-06-25 17:29:27 【问题描述】:这些是视图中涉及的模型:
class Movie(models.Model):
title_original = models.CharField(max_length=300,
db_column='titulooriginal')
title_translated = models.CharField(max_length=300, blank=True,
db_column='titulotraducido')
thumbnail = models.CharField(max_length=300, blank=True,
db_column='imagen')
length = models.CharField(max_length=75, db_column='duracion')
rating = models.CharField(max_length=75, db_column='censura')
genre = models.CharField(max_length=75, db_column='genero')
country_of_origin = models.CharField(max_length=150, db_column='pais')
trailer = models.CharField(max_length=300, blank=True, db_column='trailer')
synopsis = models.CharField(max_length=3600, blank=True,
db_column='sinopsis')
cast = models.CharField(max_length=300, blank=True, db_column='elenco')
director = models.CharField(max_length=150, db_column='director')
slug = models.SlugField(unique=True, blank=True)
tsc = models.DateTimeField(auto_now=False, auto_now_add=True, db_column='tsc', null=True)
tsm = models.DateTimeField(auto_now=True, auto_now_add=True, db_column='tsm', null=True)
class Meta:
db_table = u'peliculas'
def __unicode__(self):
return self.title_original
class ShowTime(models.Model):
LANGUAGE_ESPANOL = 'Espanol'
LANGUAGE_SUBTITLED = 'Subtitulada'
LANGUAGE_CHOICES = (
(LANGUAGE_ESPANOL, LANGUAGE_ESPANOL),
(LANGUAGE_SUBTITLED, LANGUAGE_SUBTITLED))
movie = models.ForeignKey(Movie, db_column='idpelicula')
theater = models.ForeignKey(Theater, db_column='idcine',
null=True)
time = models.TimeField(null=True, db_column='hora')
type_3d = models.NullBooleanField(db_column=u'3d')
type_xd = models.NullBooleanField(null=True, db_column='xd')
type_gtmax = models.NullBooleanField(null=True, db_column='gtmax')
type_vip = models.NullBooleanField(null=True, db_column='vip')
type_imax = models.NullBooleanField(null=True, db_column='imax')
language = models.CharField(max_length=33, blank=True, db_column='idioma',
choices=LANGUAGE_CHOICES,
default=LANGUAGE_ESPANOL)
city = models.ForeignKey(City, db_column='idciudad')
start_date = models.DateField(blank=True, db_column='fecha_inicio')
end_date = models.DateField(blank=True, db_column='fecha_fin')
visible = models.NullBooleanField(null=True, db_column='visible')
tsc = models.DateTimeField(auto_now=False, auto_now_add=True, db_column='tsc', null=True)
tsm = models.DateTimeField(auto_now=True, auto_now_add=True, db_column='tsm', null=True)
class Meta:
db_table = u'funciones'
def __unicode__(self):
return (unicode(self.theater) + " " + unicode(self.movie.title_original) + " " + unicode(self.time))
另外,这是查询模型的视图:
def list_movies(request, time_period):
city = utils.get_city_from_request(request)
if time_period == 'proximas-dos-horas':
(start_date,
end_date,
hours_start,
hours_end) = utils.get_datetime_filters_from_time_period(time_period)
else:
(start_date,
end_date) = utils.get_datetime_filters_from_time_period(time_period)
if not start_date: # 404 for invalid time periods
raise Http404
movies = Movie.objects.filter(
showtime__city=city.code,
showtime__visible=1,
).order_by('-tsm').distinct()
if time_period == 'proximas-dos-horas':
movies = movies.filter(
showtime__start_date__lte=start_date,
showtime__end_date__gte=end_date,
showtime__time__range=(hours_start, hours_end))
elif time_period == 'proximos-estrenos':
movies = movies.filter(
showtime__start_date=None,
showtime__end_date=None,
)
else:
movies = movies.filter(
showtime__start_date__lte=start_date,
showtime__end_date__gte=end_date)
context = 'movies': movies, 'city': city, 'time_period': time_period
return render_to_response('list_movies.html', context,
context_instance=RequestContext(request))
目前此视图在数据库中消耗大量资源,这导致浏览器上 Web 事务的响应时间较短。我将应用程序与 New Relic 监控软件连接,以分析应用程序和数据库级别的事务。这是我得到的跟踪细节:
我想得到一些关于优化这个视图的建议,以便数据库资源的消耗降到最低
非常感谢!
【问题讨论】:
请注意,您可能想将showtime__start_date=None
更改为showtime__start_date__isnull=True
showtime__start_date 或 showtime__end_date 是否有任何索引。 new relic 是否允许您在查询中执行和解释计划。如果是这样,请发布它,因为它肯定有助于诊断问题
【参考方案1】:
我不知道您的问题的背景,但我的 2 条建议是:
首先,考虑您的数据模型中的一些变化。 ShowTime
类有一个指向City
的外键和一个指向Theater
的外键,看起来有点多余。就个人而言,我更喜欢去规范化地址,例如:
class Theater(models.Model):
name = models.CharField(max_length=48)
# Location fields.
geo_country = models.CharField(max_length=48)
geo_country_code = models.CharField(max_length=2)
geo_locality = models.CharField(max_length=48)
geo_street = models.CharField(max_length=48, blank=True, default="")
geo_address = models.CharField(max_length=120, blank=True, default="")
class ShowTime(models.Model):
theater = models.ForeignKey(Theater)
这样,您可以将 JOIN 保存到 City
表中,并且可以从您的数据模型中删除。
其次,阅读Django ORM的select_related feature。
祝你玩得开心。
【讨论】:
以上是关于如何在views.py上优化Django SQL SELECT Query?的主要内容,如果未能解决你的问题,请参考以下文章
Django views.py 版本的 SQL Join 与多表查询
django框架学习六:优化views.py文件,使用rest_framework中的APIVew和Response返回
如何通过 Ajax jQuery 将简单数据发送到 Django 中的views.py?