Djangoからicotainsへの翻訳
10691 ワード
サマリ Django
においてPostgreSQL
が使用される場合、<something>.filter(<field>__icontains=<target>)
はilike
ではなくUPPER(field) like UPPER(target)
に変換される.field
にインデックスが付いている場合は、インデックスを付けることはできません.ilike
でインデックスを付ける必要があります.これらの部分は硬いSQLを使うべきです.
に期待 from django.db import models
from django.contrib.postgres.indexes import GinIndex
class Post(models.Model):
title = models.CharField(blank=False, null=False, max_length=50)
content = models.TextField(blank=True, null=False)
class Meta:
indexes = [
GinIndex(
name="title_idx", fields=["title"], opclasses=["gin_trgm_ops"]
),
]
前述のように、Post
モデルのtitle
にインデックスを作成し、次のSQLを解放します.SELECT "board_post"."id",
"board_post"."issued_date",
"board_post"."last_modified",
"board_post"."title",
"board_post"."content"
FROM "board_post"
WHERE ("board_post"."issued_date" >= '2020-12-28T19:51:54.775082+09:00'::timestamptz AND "board_post"."issued_date" <= '2021-06-28T19:51:54.775025+09:00'::timestamptz AND "board_post"."title"::text ILIKE '%테스트%')
ORDER BY "board_post"."issued_date" DESC
LIMIT 21;
39ミリ秒もかかり、インデックスがよく利用されているのがわかります.
UPPERによるトラブルシューティング
前のクエリーと同じですが、表示されるクエリーのみが少し異なります.SELECT "board_post"."id",
"board_post"."issued_date",
"board_post"."last_modified",
"board_post"."title",
"board_post"."content"
FROM "board_post"
WHERE ("board_post"."issued_date" >= '2020-12-28T19:51:54.775082+09:00'::timestamptz AND "board_post"."issued_date" <= '2021-06-28T19:51:54.775025+09:00'::timestamptz AND UPPER("board_post"."title"::text) ILIKE UPPER('%테스트%'))
ORDER BY "board_post"."issued_date" DESC
LIMIT 21;
以上の問い合わせはどのくらいかかりますか?285ミリ秒かかりました.どうして.
テーブルにインデックスが全く使用されていないため、フルスキャン中です.そして、張高は上記のようにicontains
翻訳される.q = Post.objects.filter(title__icontains="테스트")
print(q.query)
どんな結果になるのでしょうか.UPPER("board_post"."title"::text) LIKE UPPER(%테스트%))
上図に示すように、両側にupperを適用するsqlが表示されます.したがって、インデックスは取得できません.
しゅうふく
以上の場合、extra
を用いて条件文にクエリー文を直接挿入して訂正することができる.下に書いてください.<queryset>.extra(
where=[""""board_post"."title"::text ILIKE %s"""], params=[f"%테스트%"]
)
前述したように、ilike
を強制的に使用して修正することができる.最初の予想と同じクエリーを使用してインデックスを作成できるようになりました.
Reference
この問題について(Djangoからicotainsへの翻訳), 我々は、より多くの情報をここで見つけました
https://velog.io/@heka1024/Django에서-icontains의-번역
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
from django.db import models
from django.contrib.postgres.indexes import GinIndex
class Post(models.Model):
title = models.CharField(blank=False, null=False, max_length=50)
content = models.TextField(blank=True, null=False)
class Meta:
indexes = [
GinIndex(
name="title_idx", fields=["title"], opclasses=["gin_trgm_ops"]
),
]
前述のように、Post
モデルのtitle
にインデックスを作成し、次のSQLを解放します.SELECT "board_post"."id",
"board_post"."issued_date",
"board_post"."last_modified",
"board_post"."title",
"board_post"."content"
FROM "board_post"
WHERE ("board_post"."issued_date" >= '2020-12-28T19:51:54.775082+09:00'::timestamptz AND "board_post"."issued_date" <= '2021-06-28T19:51:54.775025+09:00'::timestamptz AND "board_post"."title"::text ILIKE '%테스트%')
ORDER BY "board_post"."issued_date" DESC
LIMIT 21;
39ミリ秒もかかり、インデックスがよく利用されているのがわかります.UPPERによるトラブルシューティング
前のクエリーと同じですが、表示されるクエリーのみが少し異なります.SELECT "board_post"."id",
"board_post"."issued_date",
"board_post"."last_modified",
"board_post"."title",
"board_post"."content"
FROM "board_post"
WHERE ("board_post"."issued_date" >= '2020-12-28T19:51:54.775082+09:00'::timestamptz AND "board_post"."issued_date" <= '2021-06-28T19:51:54.775025+09:00'::timestamptz AND UPPER("board_post"."title"::text) ILIKE UPPER('%테스트%'))
ORDER BY "board_post"."issued_date" DESC
LIMIT 21;
以上の問い合わせはどのくらいかかりますか?285ミリ秒かかりました.どうして.
テーブルにインデックスが全く使用されていないため、フルスキャン中です.そして、張高は上記のようにicontains
翻訳される.q = Post.objects.filter(title__icontains="테스트")
print(q.query)
どんな結果になるのでしょうか.UPPER("board_post"."title"::text) LIKE UPPER(%테스트%))
上図に示すように、両側にupperを適用するsqlが表示されます.したがって、インデックスは取得できません.
しゅうふく
以上の場合、extra
を用いて条件文にクエリー文を直接挿入して訂正することができる.下に書いてください.<queryset>.extra(
where=[""""board_post"."title"::text ILIKE %s"""], params=[f"%테스트%"]
)
前述したように、ilike
を強制的に使用して修正することができる.最初の予想と同じクエリーを使用してインデックスを作成できるようになりました.
Reference
この問題について(Djangoからicotainsへの翻訳), 我々は、より多くの情報をここで見つけました
https://velog.io/@heka1024/Django에서-icontains의-번역
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
SELECT "board_post"."id",
"board_post"."issued_date",
"board_post"."last_modified",
"board_post"."title",
"board_post"."content"
FROM "board_post"
WHERE ("board_post"."issued_date" >= '2020-12-28T19:51:54.775082+09:00'::timestamptz AND "board_post"."issued_date" <= '2021-06-28T19:51:54.775025+09:00'::timestamptz AND UPPER("board_post"."title"::text) ILIKE UPPER('%테스트%'))
ORDER BY "board_post"."issued_date" DESC
LIMIT 21;
q = Post.objects.filter(title__icontains="테스트")
print(q.query)
UPPER("board_post"."title"::text) LIKE UPPER(%테스트%))
以上の場合、
extra
を用いて条件文にクエリー文を直接挿入して訂正することができる.下に書いてください.<queryset>.extra(
where=[""""board_post"."title"::text ILIKE %s"""], params=[f"%테스트%"]
)
前述したように、ilike
を強制的に使用して修正することができる.最初の予想と同じクエリーを使用してインデックスを作成できるようになりました.Reference
この問題について(Djangoからicotainsへの翻訳), 我々は、より多くの情報をここで見つけました https://velog.io/@heka1024/Django에서-icontains의-번역テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol