Skip to content

【ユーザーグループ】グループに紐づくユーザーのパフォーマンス改善 #4365

@teratai3

Description

@teratai3

概要

だれでも登録できるような会員サイトでは、管理画面のグループ管理ページにおいてタイムアウトが発生するか可能性が高いです。
basercmsの会員機能を利用したフリー会員サイト機能を実装しているプロジェクトはあると思われるため、比較的優先度は高いと思われます。
そのため、パフォーマンス改善をしていただきたいです。

baserCMS version : 5.3.2

問題

現状の実装では以下のようにユーザーグループ削除前のチェックに contain => ['Users'] を使用しています。

$userGroup = $this->UserGroups->get($id, ['contain' => ['Users']]);
if (!empty($userGroup->users)) {
    throw new BcException(...);
}

https://github.com/baserproject/basercms/blob/5.2.3/plugins/baser-core/src/Service/UserGroupsService.php#L183-L186

この実装では、ユーザーグループに所属するユーザーが大量にいる場合、
チェックのためだけにグループ内の全ユーザーを 取得するため、処理時間が大幅に増加し最悪タイムアウトします。

再現手順

  1. operators などの適当なユーザーグループに 4万系程度のユーザーを作成します。
    (検証ではシードを使いダミーユーザーを作成しました。)
  2. /baser/admin/baser-core/user_groups/index にアクセスします
  3. 作成したユーザーが所属しているユーザーグループを削除を試みます。
  4. 環境によっては、タイムアウトが発生するまたは、極端に時間がかかります。
Image

※ これは未検証でおそらくですが、ローカル内のdockerだから4万件程度耐えれていますが、
レンタルサーバーのような限られたリソース内ならもっと早くにタイムアウトする可能性が考えられます。

対応方法

EXISTS クエリで存在確認のみ行うよう変更する。または、LIMIT 1で存在確認を行う。
できれば、EXISTSがパフォーマンスが良さそうです。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions