最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Django中select_related查詢優(yōu)化的具體實(shí)現(xiàn)

 更新時(shí)間:2025年12月24日 10:25:06   作者:言之。  
本文介紹了Django ORM中的N+1查詢問(wèn)題及其解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

目標(biāo)

  • 理解 N+1 查詢問(wèn)題及其性能影響
  • 掌握 select_related 的作用和使用方法
  • 能夠分析 Django ORM 生成的 SQL 語(yǔ)句
  • 在實(shí)際開發(fā)中正確應(yīng)用查詢優(yōu)化技巧

一、問(wèn)題引入:N+1 查詢問(wèn)題

1.1 數(shù)據(jù)模型定義

# models.py
class Author(models.Model):
    name = models.CharField(max_length=100)
    country = models.CharField(max_length=50)

class Book(models.Model):
    title = models.CharField(max_length=200)
    author = models.ForeignKey(Author, on_delete=models.CASCADE)
    publish_date = models.DateField()

1.2 存在性能問(wèn)題的代碼

# views.py (存在N+1查詢問(wèn)題)
books = Book.objects.all()
for book in books:
    print(f"書名:{book.title}, 作者:{book.author.name}")

1.3 對(duì)應(yīng)的 SQL 查詢

-- 第一次查詢:獲取所有書籍
SELECT 
    "library_book"."id",
    "library_book"."title", 
    "library_book"."author_id",
    "library_book"."publish_date"
FROM "library_book";

-- 后續(xù) N 次查詢:為每本書單獨(dú)查詢作者
SELECT "library_author"."id", "library_author"."name", "library_author"."country"
FROM "library_author" WHERE "library_author"."id" = 1;

SELECT "library_author"."id", "library_author"."name", "library_author"."country"
FROM "library_author" WHERE "library_author"."id" = 2;

-- ... 依此類推,產(chǎn)生 N+1 次查詢

問(wèn)題分析:如果有 100 本書,將產(chǎn)生 101 次數(shù)據(jù)庫(kù)查詢,嚴(yán)重影響性能。

二、解決方案:select_related

2.1select_related的基本用法

# views.py (優(yōu)化后的代碼)
books = Book.objects.select_related('author').all()
for book in books:
    print(f"書名:{book.title}, 作者:{book.author.name}")

2.2 優(yōu)化后的 SQL

SELECT 
    "library_book"."id",
    "library_book"."title",
    "library_book"."author_id", 
    "library_book"."publish_date",
    -- 通過(guò) JOIN 一次性獲取作者信息
    "library_author"."id",
    "library_author"."name",
    "library_author"."country"
FROM "library_book"
INNER JOIN "library_author" 
    ON ("library_book"."author_id" = "library_author"."id");

優(yōu)化效果:無(wú)論有多少本書,都只執(zhí)行 1 次 數(shù)據(jù)庫(kù)查詢。

三、select_related的深入使用

3.1 深度關(guān)聯(lián)查詢

擴(kuò)展數(shù)據(jù)模型:

class Country(models.Model):
    name = models.CharField(max_length=50)
    code = models.CharField(max_length=3)

class Author(models.Model):
    name = models.CharField(max_length=100)
    country = models.ForeignKey(Country, on_delete=models.CASCADE)

class Book(models.Model):
    title = models.CharField(max_length=200)
    author = models.ForeignKey(Author, on_delete=models.CASCADE)
    publish_date = models.DateField()

深度關(guān)聯(lián)查詢:

# 一次性獲取 Book -> Author -> Country 的所有數(shù)據(jù)
books = Book.objects.select_related('author__country').all()
for book in books:
    print(f"{book.title} - {book.author.name} - {book.author.country.name}")

對(duì)應(yīng)的 SQL:

SELECT 
    "library_book"."id",
    "library_book"."title",
    "library_book"."author_id",
    "library_book"."publish_date",
    -- 作者表字段
    "library_author"."id",
    "library_author"."name", 
    "library_author"."country_id",
    -- 國(guó)家表字段(通過(guò)第二次 JOIN)
    "library_country"."id",
    "library_country"."name",
    "library_country"."code"
FROM "library_book"
INNER JOIN "library_author" 
    ON ("library_book"."author_id" = "library_author"."id")
INNER JOIN "library_country" 
    ON ("library_author"."country_id" = "library_country"."id");

四、實(shí)踐技巧與注意事項(xiàng)

4.1 查看生成的 SQL 語(yǔ)句

方法1:使用 query 屬性

books = Book.objects.select_related('author')
print(books.query)

方法2:配置 Django SQL 日志
settings.py 中添加:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'level': 'DEBUG',
        },
    },
}

4.2 使用原則

  1. 適用場(chǎng)景

    • 一對(duì)一關(guān)系(OneToOneField)
    • 多對(duì)一關(guān)系(ForeignKey)
    • 需要立即訪問(wèn)關(guān)聯(lián)對(duì)象字段時(shí)
  2. 不適用場(chǎng)景

    • 多對(duì)多關(guān)系(ManyToManyField)
    • 反向的多對(duì)一關(guān)系
    • 對(duì)于這些情況,應(yīng)該使用 prefetch_related
  3. 注意事項(xiàng)

    • 不要過(guò)度使用深度關(guān)聯(lián)
    • 考慮查詢返回的數(shù)據(jù)量
    • 只在確實(shí)需要訪問(wèn)關(guān)聯(lián)對(duì)象時(shí)使用

五、總結(jié)對(duì)比

5.1 性能對(duì)比表

查詢方式查詢次數(shù)適用場(chǎng)景SQL 類型
普通查詢N+1 次不確定是否需要關(guān)聯(lián)對(duì)象簡(jiǎn)單查詢 + 多次關(guān)聯(lián)查詢
select_related1 次確定需要訪問(wèn)關(guān)聯(lián)對(duì)象的所有字段JOIN 查詢

5.2 核心要點(diǎn)

  1. 解決問(wèn)題:N+1 查詢問(wèn)題
  2. 實(shí)現(xiàn)原理:使用 SQL JOIN 語(yǔ)句一次性加載關(guān)聯(lián)數(shù)據(jù)
  3. 使用語(yǔ)法Model.objects.select_related('foreign_key_field')
  4. 深度關(guān)聯(lián):使用雙下劃線 'field__related_field'
  5. 記憶口訣:“往前拿,用 select_related

5.3 最佳實(shí)踐

# 好的實(shí)踐:明確知道需要作者信息
books = Book.objects.select_related('author').filter(publish_date__year=2023)
for book in books:
    # 這里會(huì)頻繁訪問(wèn) author 的字段
    display_info = f"{book.title} by {book.author.name}"

# 不好的實(shí)踐:不確定是否需要關(guān)聯(lián)對(duì)象
books = Book.objects.select_related('author').filter(publish_date__year=2023)
for book in books:
    # 如果這里根本不訪問(wèn) book.author,就浪費(fèi)了 JOIN 的性能
    print(book.title)

到此這篇關(guān)于Django中select_related查詢優(yōu)化的具體實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Django select_related查詢優(yōu)化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

加查县| 沿河| 香港 | 理塘县| 湘西| 高邑县| 清徐县| 苍梧县| 德格县| 日土县| 贡觉县| 漳浦县| 磐石市| 循化| 濮阳市| 会昌县| 米易县| 石狮市| SHOW| 远安县| 石柱| 黄山市| 大悟县| 辽阳县| 沐川县| 固安县| 沧州市| 九寨沟县| 武冈市| 商水县| 保德县| 靖州| 辽阳市| 巴里| 水富县| 温州市| 阿克陶县| 泰州市| 东宁县| 郎溪县| 崇阳县|