クロールにあなたのウェブサイトを遅らせることができるジャンゴ機能


order_by を通してDjango QuerySetを注文すると、DJangoは、指定された列で行を注文するようにデータベースに依頼します.
命令されている行数があまり大きくない限り、この操作は速くなければなりません.しかし、order_byでビルドを使用すると、非常に高価で低速な操作の一連を引き起こすことができます.データベースからランダム行を取得します.

非ランダムに1つのランダム行を読む
ランダムな記録を得る方法でのDjangoの造りは、order_by('?')[0]を通してあります.Djangoドキュメント自身がthis warningを与えるという点に注意してください:

order_by('?') queries may be expensive and slow


パフォーマンスが悪いのは、djangoが以下の非効率的なSQLを生成するという事実です.
SELECT * FROM entry ORDER BY RAND() LIMIT 1
SQLを壊しましょう.
SELECT * FROM entry
これは、entryテーブルからすべての列を含むようにデータベースに指示します.
ORDER BY RAND()
これは、データベースに対して、行ごとに乱数を生成するように指示します(使用するデータベースによって異なります.
LIMIT 1
これは、最小の1つの生成された番号をスキャンするデータベースを教えてください.この行を読み込む.
そのシンクを入れてください:我々が100000の行を持っているならば、100000の乱数は最初に生成されます.乱数を生成するのは遅いです、スキャンは迅速ではありません.遠近法のためにこの操作はマイニングBitcoinのように多くのにおいがする最終的にすべての私たちはそれを取得するデータベースから1行を読んでいる!小さな給料でたくさんの仕事をしなければならない.
データベースに多くの行があって、order_by('?')[0]が使われるならば、悪いパフォーマンスを予想してください.

つのランダム行を効率的に読む
要するにデータベースはランダムではない.アプリケーションもあります.したがって、データベースとアプリケーション間の分割の責任を考慮します.
データベースレベルの
  • は、行
  • の数を決定します
    アプリケーションレベルの
  • は0とそのカウントの間の乱数を取得します.
  • データベースレベルの
  • は、そのインデックスの行を選択します.
  • これは、2つのデータベース読み込みが実行されることを意味するが、それらは非常に効率的な操作であり、したがって、テーブルをコピーして、ランダムにすべての行を命じるデータベースよりかなり速い.
    そのことを念頭に置いて、Django Doctorがプル・リクエストを見直したときにこのアドバイスを与えている理由です.


    自己
    このようにカスタムモデルマネージャにロジックを移動させることで、ソリューションの階層化を改善することを考えてください.
    from random import randint
    
    from django.db import models, transaction
    
    
    class RandomManager(models.Manager):
    
        @transaction.atomic
        def random(self):
            index = randint(0, self.count()-1)
            return self.all()[index]
    
    class Entry(models.Model):
         objects = RandomManager()
    
    random_item = Entry.objects.random()
    
    カウントと行の両方が同じトランザクションで起こるようにするために order_by('?')[0] の使用に注意してください.
  • カウントされた後、ランダム行が読み込まれる前に、テーブルの最後の行が削除されました.
  • 生成された乱数はテーブルの最後の行でした.
  • 非常にまれな状況の下で原子取引なしで、transaction.actomicが起こることができました.

    あなたのDjango Codebaseは、このように技術負債を持ちますか?
    Django Doctorを見つけることができると一般的なジャンゴ技術の債務の40種類以上を修正し、あなたのためにもreview your GitHub Pull Requestsすることができます.