2017-11-09 9 views
0

私が書いているアプリに.exists()というクエリがあります。私はそれを最適化したい。Django `.exists()`クエリを最適化する

現在のORM式は次のようになりますSQL生成:私は手動で上記のSQLを変更するので、個々の表の列を削除した場合

Limit (cost=176.60..176.63 rows=1 width=223) 
    -> Unique (cost=176.60..177.40 rows=29 width=223) 
     -> Sort (cost=176.60..176.67 rows=29 width=223) 
       Sort Key: id, ...SNIP... 
       -> Index Scan using ...SNIP... on ...SNIP... (cost=0.43..175.89 rows=29 width=223) 
        Index Cond: (user_id = 6) 
        Filter: ...SNIP... 

:実行計画は、次のようになります

SELECT DISTINCT 
    (1) AS "a", 
    "the_model"."id", 
... snip every single column on the_model 
FROM "the_model" 
WHERE (
...snip criteria... 
LIMIT 1 

SELECT DISTINCT 
    (1) AS "a", 
FROM "the_model" 
WHERE (
...snip criteria... 
LIMIT 1 

説明プランにはいくつかの例がありますそれは素晴らしいことです。

Limit (cost=0.43..6.48 rows=1 width=4) 
    -> Index Scan using ..SNIP... on ..SNIP... (cost=0.43..175.89 rows=29 width=4) 
     Index Cond: (user_id = 6) 
     Filter: ..SNIP... 

私が使用してORMの表現を変更することができます。私はここに保存コストはマイナーですが、これも浅い実行計画を得、クエリからDISTINCTキーワードを除去することにより、さらに行くことができます

Limit (cost=0.43..175.89 rows=1 width=4) 
    -> Unique (cost=0.43..175.89 rows=1 width=4) 
     -> Index Scan using ...SNIP... on ...SNIP... (cost=0.43..175.89 rows=29 width=4) 
       Index Cond: (user_id = 6) 
       Filter: ...SNIP... 

.only('id')を使用して1つのフィールドのみを選択します。しかし、それは私が望む結果にはなりません。 idで不要な並べ替えをしています。理想的には、.only(None)を実行したいと思います。なぜなら、ここにはどの列も必要ないからです。彼らは体重を加えるだけです。

可能であれば、DISTINCTというキーワードも削除したいと思います。列が削除されても実行時間が長くかかるとは思わない。

.exists()はブール値を返すので、これはボード全体で実行できるようです。返される列は何にも使用されません。クエリが複雑になり、パフォーマンスが低下します。

+2

Djangoのどのバージョンを使用していますか、どのようなコードがそのクエリを引き起こしていますか?私は 'User.objects.exists()'を試してみると、 'FROM" auth_user "LIMIT 1"という 'SELECT(1)AS 'を実行しています。 – Alasdair

+0

私はDjango 1.11.5を使用しています。カスタムコードがこれを妨げているかどうかを確認し、追加の列を選択させるかどうかを調べます。 –

+0

私が気づいていなかった場所のQuerySetに '.distinct()'コールが適用されました。これはすべてを台無しにしていた。 –

答えて

0

クエリセットの作成中に.distinct()が私の.exists()の前に呼び出されていることがわかりました。不必要に列が選択されていました。