2016-12-23 9 views
3

1Mレコードのテーブルに10kレコードを返すクエリの最後の50レコードを取得したいとしましょう。 (2データベースがヒットのコストで)最初のN個のレコードをスライスする前にクエリーセットを逆順に並べるか、最後のN個のレコードをスライスするかを数えますか?

data = MyModel.objects.filter(criteria=something).order_by('-pk')[:50] 

は私も行うことができます:

# assume I don't care about new records being added between 
# the two queries being executed 
index = MyModel.objects.filter(criteria=something).count() 
data = MyModel.objects.filter(criteria=something)[index-50:] 

と普通のリレーショナルデータベースのための優れている私は、(発注の計算コストで)行うことができますcriteriaのインデックスはありません(私の場合はポストグルです;柱状のストレージも何も表示されません)?最も重要なことは、なぜですか?

テーブルまたはクエリーセットがかなり大きい場合(たとえば10Mのローテーブルの100kレコード)、答えは変わりますか?

+0

'.filter'を使用すると、Djangoは意味のある順序を強制しますか?通常、SQLデータベースでは、*最後の50行*は 'order by'または同等のものを使用する場合にのみ意味があります。同じクエリを再度実行すると、同じ順序で行が返されないことがあります。 –

+0

私はちょうど合理的な最近の顧客のレビューを表示したいダッシュボードを作成するコンテキストでこれを求めています。注文の厳密さは、この特定のケースでは重要ではありません。 – Escher

+0

*合理的に最近の*は、 'order by'またはそれに相当するものがないと意味がありません。 –

答えて

5

この1つは非常に遅くなるだろう

data = MyModel.objects.filter(criteria=something)[index-50:] 

なぜそれが

SELECT * FROM myapp_mymodel OFFEST (index-50) 

あなたがここに任意の順序を強制していないに変換するので、サーバーは、結果をcalulcateしているつもりされているため、設定してその最後にジャンプし、それは多くの読書を伴うことになり、非常に遅くなります。 count()のクエリがそれほど魅力的ではないことも忘れてはいけません。

OTH、これはあなたが主キーの逆の順序であり、あなたが

data = MyModel.objects.filter(criteria=something).order_by('pk')[:50] 
と同じようにすぐに取り出すことができる最初の50と第一50を取得して、高速

data = MyModel.objects.filter(criteria=something).order_by('-pk')[:50] 

になるだろう

これはあなたが本当にすべきことです。

data1 = MyModel.objects.filter(criteria=something).order_by('-pk')[:50] 
data2 = MyModel.objects.filter(criteria=something).order_by('pk')[:50] 

プライマでの注文コストyキーは非常に低いです。

関連する問題