MySQLはデータベースのN+1クエリ問題を解決します

MySQLはデータベースのN+1クエリ問題を解決します

導入

HibernateやMyBatisなどのORMフレームワークでは、部門に関連付けられたユーザーオブジェクトなどの関連オブジェクトを設定できます。
n人のユーザーが見つかった場合、n個の部門クエリが必要です。ユーザーをクエリすることは選択操作であり、ユーザーの関連をクエリすることは
dept は n 回なので、n+1 の問題ですが、1+n と呼ぶ方が適切です。

mybatisの設定

ユーザーマッパー.xml

<resultMap id="BaseResultMap" タイプ="testmaven.entity.User">
  <id 列="id" jdbcType="INTEGER" プロパティ="id" />
  <結果列="名前" jdbcType="VARCHAR" プロパティ="名前" />
  <結果列="年齢" jdbcType="INTEGER" プロパティ="年齢" />
  <結果列="dept_id" jdbcType="INTEGER" プロパティ="deptId" />
  <関連付けプロパティ="dept" 列="dept_id" fetchType="eager" select="testmaven.mapper.DeptMapper.selectByPrimaryKey" ></関連付け>
 </結果マップ>

データテーブルは次のとおりです。

部門テーブル

|ID|名前|

ユーザーテーブル

|id|名前|部門ID|

要件は、次の構造を持つデータを取得することです。

[
  { "id":1, "name":"テスト", "department_id":1, "department":{ "id":1, "name":"テスト部門"
    }
  }
]

方法1: ループクエリ

ユーザーリストを照会する

対応する部門情報を照会するための循環ユーザーリスト

$users = $db->query('SELECT * FROM `user`'); foreach($users as &$user) {
  $users['department'] = $db->query('SELECT * FROM `department` WHERE `id` = '.$user['department_id']);
}

この方法では、1+N クエリ (リストへのクエリ 1 つ、部門へのクエリ N つ) が実行されますが、パフォーマンスが最も低いため、お勧めできません。

方法2: テーブルを結合する

結合テーブルを通じてユーザーと部門のデータを照会する

返されたデータの処理

$users = $db->query('SELECT * FROM `user` INNER JOIN `department` ON `department`.`id` = `user`.`department_id`'); // 手動処理では、必要な構造として結果が返されます

この方法には実際には制限があります。ユーザーと部門が同じサーバー上にない場合、テーブルを結合することはできません。

方法3: 1+1クエリ

このメソッドはまずユーザーリストを一度照会します

リストから部門IDを取り出して配列を形成する

ステップ2で部門を問い合わせる

最終データを統合する

コードは大まかに次のようになります。

$users = $db->query('SELECT * FROM `user`');
$departmentIds = [ ]; foreach($users を $user として) { if(!in_array($user['department_id'], $departmentIds)) {
    $departmentIds[] = $user['department_id'];
  }
}
$departments = $db->query('SELECT * FROM `department` WHERE id in ('.join(',',$department_id).')');
$map = []; // [部門ID => 部門項目]foreach($departments as $department) {
  $map[$department['id']] = $department;
}foreach($users を $user として) {
  $user['department'] = $map[$user['department_id']] ?? null;
 }

この方法は 2 つのテーブルに制限がなく、マイクロサービスの現在の人気を考慮すると、より優れたアプローチです。

以下もご興味があるかもしれません:
  • 少なくともn日間連続してログインしているユーザーに対するSQLクエリ
  • MySQLはすべてのカテゴリの最初のNレコードを取得します
  • MySQL で n 回以上連続して出現する数字を見つける方法

<<:  JavaScript でプロパティハイジャックを実装する方法 defineProperty

>>:  Centos8 でローカル Web サーバーを構築するための実装手順

推薦する

CSS の Display、Visibility、Opacity、rgba、z-index: -1 の違い

ウェブページ上のいくつかの要素の非表示、透明、その他のプロパティを制御する必要があることがよくありま...

JavaScript を学ぶときに知っておくべき 3 つのヒント

目次1. 魔法の拡張演算子1. 配列をコピーする2. 配列を結合する3. オブジェクトを展開する2....

Linux 脆弱性スキャンツール lynis の使用分析

はじめに: Lynis は、徹底的なセキュリティ スキャンを実行できる Unix システム用のセキュ...

Vueカスタムカプセル化ボタンコンポーネント

Vueボタンコンポーネントのカスタムカプセル化コードは参考用です。具体的な内容は次のとおりです。ボタ...

MySQL の 3 つの Binlog 形式の概要と分析

1つ。 Mysql Binlog フォーマットの紹介 Mysql binlog ログには、State...

...

LinuxにMySQLデータベース5.6のソースコードをインストールし、ログインユーザーのパスワードを変更する

この記事では、主に Linux で MYSQL データベースをインストールする方法について説明し、M...

MYSQL ローカルインストールと問題解決

序文この記事はかなり詳細で、少し面倒です。他のチュートリアル ドキュメントでは多くの手順が省略されて...

繰り返し送信、繰り返し更新、バックオフ防止に関する問題と解決策の分析

1つ。序文<br />この種の質問は、どの専門掲示板でも見かけます。Google で検索...

Springboot アプリケーションを迅速にデプロイするために Docker とアイデアを統合する詳細なプロセス

目次1. はじめに2. 環境とツール3. Dockerをインストールし、リモート接続を構成する4. ...

Windows で Nginx を使用して https サーバーとリバース プロキシを構成する際の問題

リクエストロジックフロントエンド --> https経由でnginxをリクエストnginx -...

Linux 環境に mysql5.7.36 データベースをインストールするチュートリアル

ダウンロードアドレス: https://dev.mysql.com/downloads/mysql/...

Nginx でファイル ホットリンク保護サービスを構築する方法を学ぶ例

序文多くのサイトが、ポイントやゴールドコインなど、情報のダウンロードに料金を請求していることは誰もが...

Linux lsof コマンドの使用方法の詳細な説明

lsof (開いているファイルのリスト) は、プロセスによって開かれたファイルを表示するツールです。...

<td></td> タグの境界線スタイルがブラウザに表示されない問題の解決方法

質問: 360ブラウザの互換モードなど、一部のブラウザでは、 <td style="...