大量のデータをページ分割する方法

この記事は、Ma Le による Huawei クラウド コミュニティ「アプリケーションにおける大規模データのページング処理」から共有されたものです。

導入

大量のデータの表示は常に解決しなければならない問題とみなされてきました。古典的なアイデアは、それらをバッチで表示して処理することです。

1 クエリ中の外部キーの処理

Django モデルで外部キーを使用する場合は、on_delete を通じて関連する操作を定義します。

CASCADE: カスケード動作。外部キーデータを削除すると、このデータも削除されます。
PROTECT: 保護されています。外部キーのデータを参照している限り、外部キーのデータを強制的に削除すると、Django フレームワークはエラーを報告します。
SET_NULL: 外部キー データが削除されると、このデータは NULL に設定されます (このデータを NULL に設定できる場合)。
SET_DEFAULT: デフォルト値を設定します。デフォルト値がある場合、外部キー データが削除された場合、このデータの値をデフォルトに設定します。
SET()関数:外部キーのデータが削除された場合、SET関数の値が外部キーの値として取得されます。 Set() 関数は呼び出し可能オブジェクトを受け入れることができ、呼び出し可能オブジェクトの戻り値が結果として設定されます。
DO_NOTHING: アクションは実行されません。すべてはデータベース レベルの動作に依存します。

データベースレベルの制約:

PESTRICT: デフォルトのオプション。親テーブルのレコードを削除する場合、子テーブルに関連レコードがある場合、削除は許可されません。
	NOACTION: 上記と同じ、最初に外部キーを検出します
	CASCADE: 親テーブルが削除および更新されると、子テーブルの関連付け操作も削除および更新されます。
	SET NULL: 親テーブルが削除または更新すると、子テーブルは関連するレコードの外部キー フィールドを null に設定するため、子テーブルの設計時に null 以外にすることはできません。

これらの外部キー メソッド ツールは、ユーザーが複数のテーブルに関連するクエリ タスクを処理するのに役立ちます。

1.1 Django でページネーションをクエリする方法

ページング クエリを使用するアプリケーションでは、LIMIT や OFFSET を含むクエリが非常に一般的で、ほぼすべてのクエリに ORDER BY 句が含まれます。

インデックスの並べ替えを使用すると、パフォーマンスの最適化に非常に役立ちます。そうでない場合、サーバーは大量のファイルの並べ替えを行う必要があります。

高周波の問題は、オフセット値が大きすぎることです。クエリが LIMIT のような場合、10000、20、10020 行が生成され、前の 10000 行は破棄されますが、これは非常にコストがかかります。

select * from table order by id 制限 10000, 20;

このステートメントの意味は、10000+20 レコードをクエリし、最初の 10000 レコードを削除し、最後の 20 レコードを返すことです。
このクエリでページングを実現できることは間違いありませんが、MySQL は 10000+20 レコードすべてをスキャンする必要があるため、値 10000 が大きくなるほどクエリのパフォーマンスが低下します。

すべてのページが同じ頻度でアクセスされると仮定すると、このようなクエリは平均してデータ テーブルの半分をスキャンします。これらを最適化するには、ページ分割されたビューでアクセス可能なページの最大数を制限したり、大規模なバッチ クエリをより効率的にしたりできます。

テーブル内にクエリ条件を満たすデータが多数ある場合、多くの場合、すべてを一度に取り出す必要はありませんが、これはクエリの効率やサーバーのパフォーマンスにとって大きな課題となります。たとえば、最も単純なモールでは、モールには 10,000 のデータがあるとしますが、フロントエンドでは一度に 1 ページしか表示されない可能性があります。

select * from table where xxx="xxx" 制限 10;

これは、条件を満たす 10 個のデータをクエリすることを意味します。

select * from table where xxx="xxx" 制限 10 オフセット 10;

これはページングを意味し、条件を満たす 11 番目から 20 番目のデータをクエリします。

または、最大 ID を指定してクエリを実行します

select * from table where id > #max_id# order by id limit n;

このクエリは最後の n レコードも返しますが、方法 1 のように最初の m レコードをスキャンする必要はありませんが、前のクエリ (前のページ) の最大 ID (または最小 ID) を各クエリで取得する必要があります。という方法の方が一般的に使われます。

もちろん、このクエリの問題は、最大 ID が連続していない場合、ID を取得できない可能性があることです。たとえば、現在 3 ページにいて、5 ページのデータをクエリする必要がある場合に取得できます。うまくいかない。

または、サブクエリを使用して、最初に最初の 10,000 をフィルターし、最大の ID を見つけて、要件を満たす残りの 20 を選択します。

select * from table where id > (select id from table order by id 制限 m, 1) 制限 n;

このクエリはテーブルの関連付けを必要としないため、サブクエリを通じてフィールド ID もスキャンしますが、これは前のページの最大 ID が不明な場合に推奨される使用方法です。

左右の接続方法自体の性能が悪くなる場合があります。
次のサブクエリもあります。テーブルを結合し、インデックスを追加してタプルをすばやく見つけて、タプルを読み取ります。

SELECT * FROM テーブル WHERE id <= (SELECT id FROM テーブル ORDER BY id DESC LIMIT (page-1)*pagesize ORDER BY id DESC LIMIT pagesize)

rest_framework にはページング操作モジュールが組み込まれています。employee/views.py の特定の関数に適用してみましょう。

fromrest_framework.pagination import PageNumberPagination
@api_view(['GET', 'POST'])
@permission_classes([カスタム権限])
def blog_api_view(リクエスト):
    「」「」」
    request.method == "GET" の場合:
		ページネータ = PageNumberPagination()
        # paginator.page_size = 1 設定では、ページごとに 1 つのアイテムのみが表示されます。
        paginator.page_size = 2
        task_objects = EmployeeSign.objects.all()
        result = paginator.paginate_queryset(task_objects, request)

ページングを使用しない場合、すべてのメッセージが同じページに表示されます。

シリアライザー = TaskSerializer(結果、多 = True)
        応答を返す(serializer.data)

ページング データにアクセスします。デフォルトのインターフェイス http://127.0.0.1:2001/api/tasks/ はページング 1 です。

http://127.0.0.1:2001/api/tasks/?page=1 #2,3,4...

2 まとめ

繰り返しますが、ページ分割されたクエリを使用するアプリケーションでは、LIMIT と OFFSET を含むクエリが非常に一般的であり、ほぼすべてのクエリに ORDER BY 句があります。インデックスの並べ替えを使用すると、パフォーマンスの最適化に非常に役立ちます。そうでない場合、サーバーは大量のファイルの並べ替えを行う必要があります。

高周波の問題は、オフセット値が大きすぎることです。クエリが LIMIT のような場合、10000、20、10020 行が生成され、前の 10000 行は破棄されますが、これは非常にコストがかかります。

すべてのページが同じ頻度でアクセスされると仮定すると、このようなクエリは平均してデータ テーブルの半分をスキャンします。

これらを最適化するには、ページ分割されたビューでアクセス可能なページの最大数を制限したり、大規模なクエリをより効率的にしたりできます。

クリックしてフォローし、できるだけ早くHuawei Cloudの新しいテクノロジーについて学びましょう~

JetBrains 2024 (2024.1) の最初のメジャー バージョン アップデートは オープンソースです。Microsoft も費用を支払う予定です。なぜオープンソースが依然として批判されているのでしょうか? [復旧] Tencent Cloud バックエンドがクラッシュ: コンソールにログイン後、大量のサービス エラーとデータなし ドイツも 「独立して制御可能」にする必要がある 州政府は 30,000 台の PC を Windows から Linux deepin-IDE に移行し、最終的に達成ブートストラッピング! Visual Studio Code 1.88 がリリースされました. 良い人です、Tencent は Switch を本当に「思考する学習マシン」に変えました. RustDesk リモート デスクトップが起動し、Web クライアントを再構築します. SQLite に基づく WeChat のオープン ソース ターミナル データベースである WCDB がメジャー アップグレードされました.
{{名前}}
{{名前}}

おすすめ

転載: my.oschina.net/u/4526289/blog/11051586
おすすめ