• 饮冰三年-人工智能-Python-48 Django ORM 性能优化


    这是饮冰三年-人工智能-Python-24 Django ORM增删改查的进阶篇

    一、准备 

    1:搭建好django环境,通过模型生成数据库,

    from django.db import models
    
    class Book(models.Model):
        name=models.CharField(max_length=20)
        price = models.IntegerField()
        pub_date=models.DateField()
        # 创建一对多的方法
        publish = models.ForeignKey("Publish",on_delete=models.CASCADE)
        # 创建多对多的方法
        authors=models.ManyToManyField("Author")
    class Publish(models.Model):
        name = models.CharField(max_length=32)
        city = models.CharField(max_length=32)
    
    class Author(models.Model):
        name=models.CharField(max_length=32)
        age=models.IntegerField()
    imodels.py

    2:初始化数据库

    delete from app01_publish where 1=1;
    update sqlite_sequence set seq=0 where name='app01_publish';
    insert into app01_publish(name,city)values ('清华大学出版社','北京');
    insert into app01_publish(name,city)values ('北京大学出版社','北京');
    insert into app01_publish(name,city)values ('上海商务出版社','上海');
    select * from app01_publish;
    
    delete from app01_book where 1=1;
    update sqlite_sequence set seq=0 where name='app01_book';
    insert into app01_book (name,price,pub_date,publish_id)values ('天龙八部',200,'2000-01-01',3);
    insert into app01_book (name,price,pub_date,publish_id)values ('神雕侠侣',150,'2011-01-01',3);
    insert into app01_book (name,price,pub_date,publish_id)values ('Python入门',100,'2020-01-01',1);
    insert into app01_book (name,price,pub_date,publish_id)values ('Python精通',90,'2022-01-01',1);
    select * from app01_book;
    
    delete from app01_author where 1=1;
    update sqlite_sequence set seq=0 where name='app01_author';
    insert into app01_author (name,age)values ('金庸',93);
    insert into app01_author (name,age)values ('倪匡',83);
    insert into app01_author (name,age)values ('武沛齐',83);
    insert into app01_author (name,age)values ('袁浩',83);
    select * from app01_author;
    
    delete from app01_book_authors where 1=1;
    update sqlite_sequence set seq=0 where name='app01_book_authors';
    --《天龙八部》作者:金庸、倪匡
    --《神雕侠侣》作者:金庸、
    --《Python入门》作者:武沛齐、
    --《Python精通》作者:袁浩、武沛齐
    insert into app01_book_authors (book_id,author_id)values (1,1);
    insert into app01_book_authors (book_id,author_id)values (1,2);
    insert into app01_book_authors (book_id,author_id)values (2,1);
    insert into app01_book_authors (book_id,author_id)values (3,3);
    insert into app01_book_authors (book_id,author_id)values (4,3);
    insert into app01_book_authors (book_id,author_id)values (4,4);
    select * from app01_book_authors;
    初始化数据

    3:设置数据库日志记录

    二、select_related()

    对于一对一字段(OneToOneField)和外键字段(ForeignKey),可以使用select_related 来对QuerySet进行优化

    场景一:获取每本书的名称和出版社

    def getbook_publish():
        '''获取=书籍的出版社'''
        books = Book.objects.all()
        for book in books:
            print(book.name, book.publish.name)
    [2020-07-26 17:01:39,484] (0.000) SELECT "app01_book"."id", "app01_book"."name", "app01_book"."price", "app01_book"."pub_date", "app01_book"."publish_id" FROM "app01_book"; args=()
    [2020-07-26 17:01:39,485] (0.000) SELECT "app01_publish"."id", "app01_publish"."name", "app01_publish"."city" FROM "app01_publish" WHERE "app01_publish"."id" = 3 LIMIT 21; args=(3,)
    天龙八部 上海商务出版社
    [2020-07-26 17:01:39,486] (0.000) SELECT "app01_publish"."id", "app01_publish"."name", "app01_publish"."city" FROM "app01_publish" WHERE "app01_publish"."id" = 3 LIMIT 21; args=(3,)
    神雕侠侣 上海商务出版社
    [2020-07-26 17:01:39,486] (0.000) SELECT "app01_publish"."id", "app01_publish"."name", "app01_publish"."city" FROM "app01_publish" WHERE "app01_publish"."id" = 1 LIMIT 21; args=(1,)
    Python入门 清华大学出版社
    [2020-07-26 17:01:39,487] (0.000) SELECT "app01_publish"."id", "app01_publish"."name", "app01_publish"."city" FROM "app01_publish" WHERE "app01_publish"."id" = 1 LIMIT 21; args=(1,)
    Python精通 清华大学出版社
    输出结果

    优化后

    def getbook_publish2():
        '''获取=书籍的出版社'''
        books = Book.objects.select_related("publish").all()
        for book in books:
            print(book.name, book.publish.name)
    
    
    getbook_publish2()
    [2020-07-26 17:35:50,650] (0.000) SELECT "app01_book"."id", "app01_book"."name", "app01_book"."price", "app01_book"."pub_date", "app01_book"."publish_id", "app01_publish"."id", "app01_publish"."name", "app01_publish"."city" FROM "app01_book" INNER JOIN "app01_publish" ON ("app01_book"."publish_id" = "app01_publish"."id"); args=()
    天龙八部 上海商务出版社
    神雕侠侣 上海商务出版社
    Python入门 清华大学出版社
    Python精通 清华大学出版社
    输出结果 

    二、prefetch_related()

    对于多对多字段(ManyToManyField)和一对多字段,可以使用prefetch_related()来进行优化。

    场景一:获取每个出版社出版的书(一对多)

    def get_publish_book():
        '''获取每个出版社出版的数据名称(性能较差)'''
        publishs = Publish.objects.all()
        for publish in publishs:
            for book in publish.book_set.all():
                print(publish.name, book.name)
    
    
    get_publish_book()
    View Code
    '''
    [2020-07-27 19:31:59,218] (0.000) SELECT "app01_publish"."id", "app01_publish"."name", "app01_publish"."city" FROM "app01_publish"; args=()
    [2020-07-27 19:31:59,220] (0.000) SELECT "app01_book"."id", "app01_book"."name", "app01_book"."price", "app01_book"."pub_date", "app01_book"."publish_id" FROM "app01_book" WHERE "app01_book"."publish_id" = 1; args=(1,)
    清华大学出版社 Python入门
    清华大学出版社 Python精通
    [2020-07-27 19:31:59,221] (0.000) SELECT "app01_book"."id", "app01_book"."name", "app01_book"."price", "app01_book"."pub_date", "app01_book"."publish_id" FROM "app01_book" WHERE "app01_book"."publish_id" = 2; args=(2,)
    [2020-07-27 19:31:59,222] (0.000) SELECT "app01_book"."id", "app01_book"."name", "app01_book"."price", "app01_book"."pub_date", "app01_book"."publish_id" FROM "app01_book" WHERE "app01_book"."publish_id" = 3; args=(3,)
    上海商务出版社 天龙八部
    上海商务出版社 神雕侠侣
    '''
    输出结果

    优化后

    def get_publish_book2():
        '''获取每个出版社出版的数据名称(性能较好)'''
        publishs = Publish.objects.prefetch_related('book_set')
        for publish in publishs:
            for book in publish.book_set.all():
                print(publish.name, book.name)
    
    
    get_publish_book2()
    view code
    '''
    [2020-07-27 19:39:39,342] (0.000) SELECT "app01_publish"."id", "app01_publish"."name", "app01_publish"."city" FROM "app01_publish"; args=()
    [2020-07-27 19:39:39,343] (0.000) SELECT "app01_book"."id", "app01_book"."name", "app01_book"."price", "app01_book"."pub_date", "app01_book"."publish_id" FROM "app01_book" WHERE "app01_book"."publish_id" IN (1, 2, 3); args=(1, 2, 3)
    清华大学出版社 Python入门
    清华大学出版社 Python精通
    上海商务出版社 天龙八部
    上海商务出版社 神雕侠侣
    '''
    输出结果

     场景二:获取每个出版社出版的书(多对多)

    def get_author_book():
        '''获取每个作者出版的书(性能较差)'''
        authors = Author.objects.all()
        for author in authors:
            for book in author.book_set.all():
                print(author.name, book.name)
    
    
    get_author_book()
    View Code
    '''
    [2020-07-27 19:53:17,837] (0.000) SELECT "app01_author"."id", "app01_author"."name", "app01_author"."age" FROM "app01_author"; args=()
    [2020-07-27 19:53:17,838] (0.000) SELECT "app01_book"."id", "app01_book"."name", "app01_book"."price", "app01_book"."pub_date", "app01_book"."publish_id" FROM "app01_book" INNER JOIN "app01_book_authors" ON ("app01_book"."id" = "app01_book_authors"."book_id") WHERE "app01_book_authors"."author_id" = 1; args=(1,)
    金庸 天龙八部
    金庸 神雕侠侣
    [2020-07-27 19:53:17,839] (0.000) SELECT "app01_book"."id", "app01_book"."name", "app01_book"."price", "app01_book"."pub_date", "app01_book"."publish_id" FROM "app01_book" INNER JOIN "app01_book_authors" ON ("app01_book"."id" = "app01_book_authors"."book_id") WHERE "app01_book_authors"."author_id" = 2; args=(2,)
    倪匡 天龙八部
    [2020-07-27 19:53:17,840] (0.000) SELECT "app01_book"."id", "app01_book"."name", "app01_book"."price", "app01_book"."pub_date", "app01_book"."publish_id" FROM "app01_book" INNER JOIN "app01_book_authors" ON ("app01_book"."id" = "app01_book_authors"."book_id") WHERE "app01_book_authors"."author_id" = 3; args=(3,)
    武沛齐 Python入门
    武沛齐 Python精通
    [2020-07-27 19:53:17,840] (0.000) SELECT "app01_book"."id", "app01_book"."name", "app01_book"."price", "app01_book"."pub_date", "app01_book"."publish_id" FROM "app01_book" INNER JOIN "app01_book_authors" ON ("app01_book"."id" = "app01_book_authors"."book_id") WHERE "app01_book_authors"."author_id" = 4; args=(4,)
    袁浩 Python精通
    '''
    输出结果
    def get_author_book2():
        '''获取每个作者出版的书(性能较好)'''
        authors = Author.objects.prefetch_related('book_set')
        for author in authors:
            for book in author.book_set.all():
                print(author.name, book.name)
    
    
    get_author_book2()
    View Code
    '''
    [2020-07-27 19:52:09,036] (0.000) SELECT "app01_author"."id", "app01_author"."name", "app01_author"."age" FROM "app01_author"; args=()
    [2020-07-27 19:52:09,038] (0.000) SELECT ("app01_book_authors"."author_id") AS "_prefetch_related_val_author_id", "app01_book"."id", "app01_book"."name", "app01_book"."price", "app01_book"."pub_date", "app01_book"."publish_id" FROM "app01_book" INNER JOIN "app01_book_authors" ON ("app01_book"."id" = "app01_book_authors"."book_id") WHERE "app01_book_authors"."author_id" IN (1, 2, 3, 4); args=(1, 2, 3, 4)
    金庸 天龙八部
    金庸 神雕侠侣
    倪匡 天龙八部
    武沛齐 Python入门
    武沛齐 Python精通
    袁浩 Python精通
    '''
    输出结果

    三、prefetch_related()和select_related()

    场景一:获取每个作者合作的出版社

    def get_author_publish():
        '''获取每个作者合作的出版社(性能较差)'''
        authors = Author.objects.all()
        for author in authors:
            for book in author.book_set.all():
                print(author.name, book.name, book.publish.name)
    
    
    get_author_publish()
    View Code
    '''
    [2020-07-27 20:10:40,919] (0.000) SELECT "app01_author"."id", "app01_author"."name", "app01_author"."age" FROM "app01_author"; args=()
    [2020-07-27 20:10:40,920] (0.000) SELECT "app01_book"."id", "app01_book"."name", "app01_book"."price", "app01_book"."pub_date", "app01_book"."publish_id" 
                                      FROM "app01_book" INNER JOIN "app01_book_authors" ON ("app01_book"."id" = "app01_book_authors"."book_id")
                                      WHERE "app01_book_authors"."author_id" = 1; args=(1,)
    [2020-07-27 20:10:40,921] (0.000) SELECT "app01_publish"."id", "app01_publish"."name", "app01_publish"."city" FROM "app01_publish" WHERE "app01_publish"."id" = 3 LIMIT 21; args=(3,)
    金庸 天龙八部 上海商务出版社
    [2020-07-27 20:10:40,922] (0.000) SELECT "app01_publish"."id", "app01_publish"."name", "app01_publish"."city" FROM "app01_publish" WHERE "app01_publish"."id" = 2 LIMIT 21; args=(2,)
    金庸 神雕侠侣 北京大学出版社
    [2020-07-27 20:10:40,922] (0.000) SELECT "app01_book"."id", "app01_book"."name", "app01_book"."price", "app01_book"."pub_date", "app01_book"."publish_id" 
                                      FROM "app01_book" INNER JOIN "app01_book_authors" ON ("app01_book"."id" = "app01_book_authors"."book_id") 
                                      WHERE "app01_book_authors"."author_id" = 2; args=(2,)
    [2020-07-27 20:10:40,923] (0.000) SELECT "app01_publish"."id", "app01_publish"."name", "app01_publish"."city" FROM "app01_publish" WHERE "app01_publish"."id" = 3 LIMIT 21; args=(3,)
    倪匡 天龙八部 上海商务出版社
    [2020-07-27 20:10:40,924] (0.000) SELECT "app01_book"."id", "app01_book"."name", "app01_book"."price", "app01_book"."pub_date", "app01_book"."publish_id" 
                                      FROM "app01_book" INNER JOIN "app01_book_authors" ON ("app01_book"."id" = "app01_book_authors"."book_id") 
                                      WHERE "app01_book_authors"."author_id" = 3; args=(3,)
                                      
    [2020-07-27 20:10:40,925] (0.000) SELECT "app01_publish"."id", "app01_publish"."name", "app01_publish"."city" 
                                      FROM "app01_publish" WHERE "app01_publish"."id" = 1 LIMIT 21; args=(1,)
    武沛齐 Python入门 清华大学出版社
    [2020-07-27 20:10:40,925] (0.000) SELECT "app01_publish"."id", "app01_publish"."name", "app01_publish"."city" 
                                      FROM "app01_publish" WHERE "app01_publish"."id" = 1 LIMIT 21; args=(1,)
    武沛齐 Python精通 清华大学出版社
    [2020-07-27 20:10:40,926] (0.000) SELECT "app01_book"."id", "app01_book"."name", "app01_book"."price", "app01_book"."pub_date", "app01_book"."publish_id" 
                                      FROM "app01_book" INNER JOIN "app01_book_authors" ON ("app01_book"."id" = "app01_book_authors"."book_id") 
                                      WHERE "app01_book_authors"."author_id" = 4; args=(4,)
    [2020-07-27 20:10:40,927] (0.000) SELECT "app01_publish"."id", "app01_publish"."name", "app01_publish"."city" FROM "app01_publish" WHERE "app01_publish"."id" = 1 LIMIT 21; args=(1,)
    袁浩 Python精通 清华大学出版社
    ps:
        1:先根据作者表和书籍表的关系拿到,该作者撰写的所有出版社id,循环这些书籍对应的出版社id    
    '''
    输出结果

    优化后

    def get_author_publish3():
        '''获取每个作者合作的出版社(性能一般)'''
        authors = Author.objects.prefetch_related("book_set")
        for author in authors:
            for book in author.book_set.select_related("publish"):
                print(author.name, book.name, book.publish.name)
    
    
    get_author_publish3()
    View Code
    '''
    [2020-07-27 20:27:04,048] (0.000) SELECT "app01_author"."id", "app01_author"."name", "app01_author"."age" FROM "app01_author"; args=()
    [2020-07-27 20:27:04,049] (0.000) SELECT ("app01_book_authors"."author_id") AS "_prefetch_related_val_author_id", "app01_book"."id", "app01_book"."name", "app01_book"."price", "app01_book"."pub_date", "app01_book"."publish_id" FROM "app01_book" INNER JOIN "app01_book_authors" ON ("app01_book"."id" = "app01_book_authors"."book_id") WHERE "app01_book_authors"."author_id" IN (1, 2, 3, 4); args=(1, 2, 3, 4)
    [2020-07-27 20:27:04,051] (0.000) SELECT "app01_book"."id", "app01_book"."name", "app01_book"."price", "app01_book"."pub_date", "app01_book"."publish_id", "app01_publish"."id", "app01_publish"."name", "app01_publish"."city" FROM "app01_book" INNER JOIN "app01_book_authors" ON ("app01_book"."id" = "app01_book_authors"."book_id") INNER JOIN "app01_publish" ON ("app01_book"."publish_id" = "app01_publish"."id") WHERE "app01_book_authors"."author_id" = 1; args=(1,)
    金庸 天龙八部 上海商务出版社
    金庸 神雕侠侣 北京大学出版社
    [2020-07-27 20:27:04,051] (0.000) SELECT "app01_book"."id", "app01_book"."name", "app01_book"."price", "app01_book"."pub_date", "app01_book"."publish_id", "app01_publish"."id", "app01_publish"."name", "app01_publish"."city" FROM "app01_book" INNER JOIN "app01_book_authors" ON ("app01_book"."id" = "app01_book_authors"."book_id") INNER JOIN "app01_publish" ON ("app01_book"."publish_id" = "app01_publish"."id") WHERE "app01_book_authors"."author_id" = 2; args=(2,)
    倪匡 天龙八部 上海商务出版社
    [2020-07-27 20:27:04,052] (0.000) SELECT "app01_book"."id", "app01_book"."name", "app01_book"."price", "app01_book"."pub_date", "app01_book"."publish_id", "app01_publish"."id", "app01_publish"."name", "app01_publish"."city" FROM "app01_book" INNER JOIN "app01_book_authors" ON ("app01_book"."id" = "app01_book_authors"."book_id") INNER JOIN "app01_publish" ON ("app01_book"."publish_id" = "app01_publish"."id") WHERE "app01_book_authors"."author_id" = 3; args=(3,)
    武沛齐 Python入门 清华大学出版社
    武沛齐 Python精通 清华大学出版社
    '''
    输出结果
  • 相关阅读:
    K8s PV and PVC and StorageClass
    WebSphere--WAS概念和原理解析
    K8S配置多集群访问
    ROS2学习日志:CV开发之关联Gazebo/Webots/ROS2
    CV学习日志:Orbslam使用总结
    CV学习日志:Basalt使用总结
    CV学习日志:Kalibr使用总结
    CV学习日志:CamOdoCalib使用总结
    CV学习日志:OpenVINS使用总结
    CV学习日志:搭建U2004开发环境
  • 原文地址:https://www.cnblogs.com/YK2012/p/13380413.html
Copyright © 2020-2023  润新知