MySQL + ES + MongoDB と互換性を持たせて、数億のデータのディープ ページングを実現するにはどうすればよいでしょうか?

Guanhui
リリース: 2023-04-09 11:28:02
転載
3606 人が閲覧しました

MySQL + ES + MongoDB と互換性を持たせて、数億のデータのディープ ページングを実現するにはどうすればよいでしょうか?

インタビューの質問と実際の経験

インタビュー質問: データ量が多い場合にディープ ページングを実現するにはどうすればよいですか?

面接中や面接の準備中に、上記の質問に遭遇することがあります。基本的に、データベースとテーブルを分割してインデックスを構築するという答えがほとんどです。これは非常に標準的な正解ですが、現実は常に難しいため、面接官は通常、プロジェクトのスケジュールも人員も不足している中で、どうすればディープ ページングを実現できるか、と尋ねます。

この時期、実務経験のない学生は基本的に無感覚なので、聞いてください。

痛ましい教訓

まず最初に明確にしておきたいのは、深度ページングは​​実行できますが、

前の画像:

MySQL + ES + MongoDB と互換性を持たせて、数億のデータのディープ ページングを実現するにはどうすればよいでしょうか?

ページ 142360 をクリックすると、サービスが爆発するでしょうか?

MongoDB データベースも MySQL と同じで大丈夫です。それ自体は専門的なデータベースです。処理は良くなく、せいぜい遅いです。しかし、ES が関与すると性質が異なります。 SearchAfter API をループする データの取得にはメモリ使用量の問題があり、コードを丁寧に書かないとメモリオーバーフローに直結する可能性があります。

ランダムな深さのページ ジャンプが許可されない理由

ランダムな深さのページ ジャンプが技術的な観点から許可されない理由について簡単に説明しましょう、またはディープ ページングが推奨されないのはなぜですか?

MySQL

ページングの基本原則:

SELECT * FROM test ORDER BY id DESC LIMIT 10000, 20;
ログイン後にコピー

LIMIT 10000、20 は 10020 行をスキャンすることを意味します条件を満たすものを破棄します。 最初の 10,000 行を削除し、最後の 20 行を返します。 LIMIT 1000000 であれば、100、1000100 行をスキャンする必要があり、同時実行性の高いアプリケーションでは、各クエリで 100W 以上の行をスキャンする必要があり、爆発しないのは不思議です。

MongoDB

ページングの基本原理:

db.t_data.find().limit(5).skip(5);
ログイン後にコピー

同様に、ページ番号が増加するにつれて、skip でスキップされる項目も増加します。ページ番号が非常に大きく、頻繁に使用されると、必然的に爆発的に増加します。

ElasticSearch

ビジネスの観点から見ると、ElasticSearch は一般的なデータベースではなく、検索エンジンです。フィルター条件で目的のデータが見つからない場合、深いページングを続けると、必要なデータは見つかりません。一歩下がって、クエリ用のデータベースとして ES を使用すると、ページング時に間違いなく max_result_window の制限に遭遇します。わかりましたか? 当局は最大値を教えてくれますオフセット制限は 10,000 です。

クエリ プロセス:

  • ページあたり 10 項目でページ 501 をクエリすると、クライアントは特定のノードにリクエストを送信します

  • このノードはデータを各シャードにブロードキャストし、各シャードは最初の 5010 個のデータをクエリします。

  • クエリ結果はノードに返され、データが統合されます

  • クライアントに戻る

ここから、なぜ制限する必要があるのか​​がわかります。さらに、Search After API のディープ ページ ジャンプ クエリなどのスクロール メソッドを使用する場合、毎回数千のアイテムをスクロールする必要があり、合計で数百万、数千万のデータをスクロールする必要がある場合があります。過去 20 個のデータの効率性は想像できます。

もう一度製品と合わせてください

よく言われるように、テクノロジーで解決できない問題はビジネスで解決する必要があります。

インターンシップ中、私は製品が悪であると信じていたため、ディープ ページングとページ ジャンプを実装する必要がありました。今度は混乱を修正し、ビジネスに次の変更を加える必要があります:

期間などのデフォルトのフィルタ条件をできるだけ追加します。表示されるデータ量を減らすためです。

ページジャンプの表示方法を変更し、スクロール表示に変更します。または狭い範囲でページをジャンプする場合

スクロール表示参考図:

MySQL + ES + MongoDB と互換性を持たせて、数億のデータのディープ ページングを実現するにはどうすればよいでしょうか?

小規模なページジャンプ参考図:

MySQL + ES + MongoDB と互換性を持たせて、数億のデータのディープ ページングを実現するにはどうすればよいでしょうか?

##一般的な解決策短期間での迅速な解決策には、主に次の点が含まれます。

    必須: 並べ替えフィールドとフィルター条件の場合、インデックスを設定する必要があります
  • コア: 狭い範囲のページ番号の既知のデータ、またはローリング ロードの既知のデータを使用して、オフセットを削減します
  • 補足: 対処が難しい状況に遭遇した場合は、過剰なデータを取得してある程度まで傍受することもでき、パフォーマンスへの影響は大きくありません
MySQL

元のページング SQL:

# 第一页
SELECT * FROM `year_score` where `year` = 2017 ORDER BY id limit 0, 20;
# 第N页
SELECT * FROM `year_score` where `year` = 2017 ORDER BY id limit (N - 1) * 20, 20;
ログイン後にコピー

コンテキストを通じて、次のように書き換えられます:

# XXXX 代表已知的数据
SELECT * FROM `year_score` where `year` = 2017 and id > XXXX ORDER BY id limit 20;
ログイン後にコピー

在 没内鬼,来点干货!SQL优化和诊断 一文中提到过,LIMIT会在满足条件下停止查询,因此该方案的扫描总量会急剧减少,效率提升Max!

ES

方案和MySQL相同,此时我们就可以随用所欲的使用 FROM-TO Api,而且不用考虑最大限制的问题。

MongoDB

方案基本类似,基本代码如下:

MySQL + ES + MongoDB と互換性を持たせて、数億のデータのディープ ページングを実現するにはどうすればよいでしょうか?

相关性能测试:

MySQL + ES + MongoDB と互換性を持たせて、数億のデータのディープ ページングを実現するにはどうすればよいでしょうか?

如果非要深度随机跳页

如果你没有杠过产品经理,又该怎么办呢,没关系,还有一丝丝的机会。

在 SQL优化 一文中还提到过MySQL深度分页的处理技巧,代码如下:

# 反例(耗时129.570s)
select * from task_result LIMIT 20000000, 10;
# 正例(耗时5.114s)
SELECT a.* FROM task_result a, (select id from task_result LIMIT 20000000, 10) b where a.id = b.id;
# 说明
# task_result表为生产环境的一个表,总数据量为3400万,id为主键,偏移量达到2000万
ログイン後にコピー

该方案的核心逻辑即基于聚簇索引,在不通过回表的情况下,快速拿到指定偏移量数据的主键ID,然后利用聚簇索引进行回表查询,此时总量仅为10条,效率很高。

因此我们在处理MySQL,ES,MongoDB时,也可以采用一样的办法:

  • 限制获取的字段,只通过筛选条件,深度分页获取主键ID

  • 通过主键ID定向查询需要的数据

瑕疵:当偏移量非常大时,耗时较长,如文中的 5s

推荐教程:《MySQL教程

文章来源:https://juejin.im/post/5f0de4d06fb9a07e8a19a641

以上がMySQL + ES + MongoDB と互換性を持たせて、数億のデータのディープ ページングを実現するにはどうすればよいでしょうか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:juejin.im
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート