分享

Django项目中ORM使用指定的sql语句提速30倍(强制索引)

 只怕想不到 2024-04-12 发布于湖北

    在django项目中一般都是使用ORM来操作sql语句,但是这带来了一个问题,例如:我在站点地图的代码中有这样一句:

def items(self):  return NBA.objects.values('id').filter(display=1).order_by('id'

    这个转化成sql语句大概是这样子:

SELECT `nba`.`id` FROM `nba` WHERE `nba`.`display` = 1 ORDER BY `nba`.`id` ASC LIMIT 3441 OFFSET 535000

本地测试一直都没问题,但是上传到服务器上结果发现了问题,输出的语句不知道为什么一直没用到联合索引idx_id_display,而使用联合索引的语句速度比未使用的情况下快30倍,实测USE INDEX (idx_id_display)

SELECT `nba`.`id` FROM `nba` USE INDEX (idx_id_display) WHERE `nba`.`display` = 1 ORDER BY `nba`.`id` ASC LIMIT 3441 OFFSET 535000

这就带来了一个问题,如何在django的ORM中使用原生的sql语句,

原本的代码:

class DetailSitemap(LimitSitemap):    changefreq = 'weekly'    priority = 0.6    def items(self):        return NBA.objects.values('id').filter(display=1).order_by('id')
def location(self, obj): return reverse('detail',args=[obj.get('id')]) def lastmod(self, obj): return datetime.now()

修改的代码如下:

from django.db import connection
class DetailSitemap(LimitSitemap): changefreq = 'weekly' priority = 0.6 def items(self): query = 'SELECT `nba`.`id` FROM `nba` USE INDEX (idx_id_display) WHERE `nba`.`display` = 1 ORDER BY `nba`.`id`' with connection.cursor() as cursor: cursor.execute(query) result = cursor.fetchall() return result
def location(self, obj): return reverse('detail', args=[obj[0]])
def lastmod(self, obj): return datetime.now()

这里面其实还有一个问题,就是修改后的代码在数据库文件中其实少了ASC LIMIT 5000 OFFSET 1540000这种偏移量,但是我在实际测试站点地图页面的时候发现确实二者的返回页面结果都是一样的,那就不纠结了。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多