【389 Directory Server講座 第7回】パフォーマンスチューニング。数万ユーザーを捌くインデックス設計とキャッシュ戦略

「LDAPが遅い」と言われたら、まずはログの “notes=U” を探せ。

こんにちは!「LINUX工房」管理人の「リナックス先生」です。
前回は、SSL/TLS化によるセキュリティ強化について学びました。
セキュアで可用性の高い認証基盤ができあがりましたが、ユーザー数が増えてくると、新たな敵が現れます。
それは「遅延(Latency)」です。

朝の始業時、全社員が一斉にログインしようとして認証がタイムアウトする。
住所録の検索がいつまで経っても終わらない。
これらはサーバーのスペック不足ではなく、多くの場合「設定(チューニング)不足」が原因です。

コウ君

先生、まさに今その状態です!
ユーザー数が3,000人を超えたあたりから、特定のアプリで検索がすごく重いんです。
top コマンドを見てもCPUは余裕があるし、メモリも余ってるのに、なぜか遅い。
「LDAPサーバーなんてこんなもん」って諦めるしかないんですか?
RDBMSみたいにインデックスとか貼れないんですか?

リナックス先生

コウ君、諦めるのはまだ早いわ。
LDAPサーバーは、適切なインデックスとキャッシュ設定を行えば、数万、数十万ユーザーでもミリ秒単位で応答できるポテンシャルを持っているの。
逆に言えば、デフォルト設定のまま大規模運用するのは「ギアを1速に入れたまま高速道路を走る」ようなものよ。
今回は、389 DSのエンジンルームを開けて、パフォーマンスを極限まで引き出すチューニング術を伝授するわ!

ウィンドウズ先生

はい、ウィンドウズ先生です。
Active Directoryの世界でも、インデックスのない属性でクエリを投げるとドメインコントローラーが高負荷に陥ります。
389 DSも仕組みは同じです。
特に「部分一致検索(*taro*)」と「キャッシュのメモリ割り当て」は、エンジニアの腕の見せ所です。
ログ解析からボトルネックを見つけ出し、外科手術のように設定を修正するプロの技をお見せしましょう。

本記事では、LDAP検索の仕組み、インデックスの種類と作成手順、Berkeley DBのキャッシュチューニング、そしてアクセスログ解析による「遅いクエリ」の特定方法までを徹底解説します。


第1章:なぜLDAPは遅くなるのか? 全件検索の恐怖

まず、データベースがデータを検索する仕組みを理解しましょう。
例えば、「社員番号(employeeNumber)が12345の人を探す」というクエリが来たとします。

インデックスがない場合 (Unindexed Search)

LDAPサーバーは、データベース内のすべてのエントリを1つずつ読み込み、「employeeNumberは12345か?」と確認します。
これを「全件走査(Full Table Scan)」と呼びます。
ユーザーが100人なら一瞬ですが、10万人いたら? ディスクI/Oが爆発し、CPUリソースを食いつぶし、結果が返ってくるまで数秒〜数十秒かかります。

インデックスがある場合

サーバーは「インデックスファイル(索引)」を参照します。
そこには「12345番のエントリは、データベースの〇〇番地にあります」と書かれています。
サーバーはピンポイントでそのデータだけを読みに行きます。
計算量は O(N) から O(1) (または O(log N)) に激減し、一瞬で応答します。

💡 389 DSの安全装置:nsslapd-allidsthreshold
389 DSには、「インデックスを使わない検索結果が4000件(デフォルト)を超えたら、検索を中断する」という安全装置があります。
「検索結果が見つかりません」ではなく「管理者制限を超えました」というエラーが出た場合、それはインデックスが効いていない証拠です。


第2章:インデックスの種類と設計戦略

「じゃあ全部の属性にインデックスを貼ればいいじゃん!」と思うかもしれませんが、それは間違いです。
インデックスを作成すると、書き込み(更新)時のオーバーヘッドが増え、ディスク容量も消費します。
必要な属性に、必要な種類のインデックスだけを設定するのがプロの仕事です。

主なインデックスタイプ

タイプ 略称 説明 用途例
Equality eq 完全一致検索。最も基本的かつ重要。 uid=taro, employeeNumber=1001
Substring sub 部分一致検索。検索窓での入力補完などで使用。 uid=ta*, sn=*yamada*
Presence pres その属性を持っているか(存在確認)。 mail=* (メアド持ちを全員検索)
Approximate approx あいまい検索(発音が似ている等)。英語圏向け。 あまり使われない。

デフォルトでインデックスがある属性

389 DSは、標準的な属性(cn, sn, uid, mail, objectClass など)には最初から適切なインデックスが設定されています。
追加が必要になるのは、以下のようなケースです。

  • カスタム属性: スキーマ拡張で追加した独自の属性(myCompanyIDなど)。
  • 数値属性: uidNumber, gidNumber(SambaやLinuxログインで必須)。
  • 特定用途の属性: memberOf(グループ検索用)、entryUUIDなど。

第3章:実践!インデックスの作成と再構築 (reindex)

それでは、実際にインデックスを追加してみましょう。
例として、社員番号(employeeNumber)で高速に検索できるようにします。

1. 現在のインデックスを確認

dsconf コマンドで、対象のバックエンド(通常は userRoot)の設定を確認します。

# インスタンス名: localhost, サフィックス: dc=linuxkoubou,dc=com
dsconf localhost index list --suffix "dc=linuxkoubou,dc=com"

ここに employeeNumber がなければ、インデックスはありません。

2. インデックスの作成

完全一致(eq)インデックスを追加します。

dsconf localhost index create --suffix "dc=linuxkoubou,dc=com" \
  --attr employeeNumber --type eq

注意: このコマンドを実行しただけでは、設定ファイル(dse.ldif)に定義が追加されるだけで、実際のインデックスデータは生成されません。

3. 再インデックス (Reindex) の実行

既存のデータに対してインデックスファイルを生成するタスクを実行します。
データ量が多い場合、この処理には時間がかかりますが、サービスを停止する必要はありません(オンラインReindex)。

dsconf localhost index reindex --suffix "dc=linuxkoubou,dc=com" --attr employeeNumber

タスクの進行状況は以下のコマンドで確認できます。

dsconf localhost task list

「Finished」になれば完了です。
これで、(employeeNumber=12345) という検索が一瞬で終わるようになります。

💡 プロのノウハウ:System Index
objectClassentryUUID などのシステム属性は、システムインデックスとして管理されています。
これらを誤って削除したり設定変更したりすると、サーバーのパフォーマンスが壊滅的になるので触らないようにしましょう。


第4章:メモリが命。キャッシュのチューニング (dbcache / entry cache)

インデックスがあっても、いちいちディスクを見に行っていたら遅いです。
データを可能な限りメモリ(RAM)に乗せるのが、データベースチューニングの基本です。
389 DSには2種類のキャッシュがあります。

1. Database Cache (nsslapd-dbcachesize)

バックエンドDB(Berkeley DB)が管理する、ページ単位のキャッシュです。
インデックスファイル(.db)やデータファイル自体をキャッシュします。
推奨値: /var/lib/dirsrv/slapd-{instance}/db/ 以下のファイルサイズの合計が入る大きさ。

2. Entry Cache (nsslapd-cachememsize)

LDAPエントリとしてパース(解凍)された状態のデータをキャッシュします。
検索結果を即座に返すために使われる、最も高速なキャッシュです。
推奨値: 全エントリを展開したサイズ(LDIFの総サイズに近い)が入る大きさ。

設定コマンド

例えば、物理メモリが16GBあるサーバーで、DBキャッシュに2GB、エントリキャッシュに4GBを割り当てる場合。

# DBキャッシュ (バイト単位: 2GB = 2147483648)
dsconf localhost backend config set --db-cache-size 2147483648

# エントリキャッシュ (userRootバックエンドに対して設定)
dsconf localhost backend create --suffix "dc=linuxkoubou,dc=com" --be-name userRoot --cache-mem-size 4294967296

設定変更後は、サービスの再起動が必要です。

systemctl restart dirsrv@localhost

💡 黄金比率の目安
物理メモリの全てを割り当ててはいけません。OSや他のプロセス、ファイルシステムキャッシュのために余裕を残す必要があります。
一般的には、物理メモリの 50%〜60% を389 DSのキャッシュに割り当て、残りをOSに任せるのが安全な構成です。


第5章:ログは嘘をつかない。ボトルネックの特定方法

「遅い」という感覚ではなく、数値で判断しましょう。
389 DSのアクセスログ(/var/log/dirsrv/slapd-{instance}/access)には、宝の山が埋まっています。

注目すべきパラメータ:etime

アクセスログの各行の最後にある etime は、処理にかかった時間(秒単位、小数点以下あり)を表します。
etime=0.001 なら1ミリ秒で爆速ですが、etime=2.5 なら2.5秒もかかっており、問題です。

注目すべきフラグ:notes=U

ログに notes=U という記述があったら、それは「Unindexed(インデックスなし)」検索が行われたことを意味します。
これこそが遅延の犯人です。

ログ解析コマンド(ワンライナー)

「処理に1秒以上かかった検索クエリ」を抽出するコマンド例です。

grep "SRCH" /var/log/dirsrv/slapd-localhost/access | awk -F'etime=' '$2 > 1.0 {print $0}'

「インデックスなし検索(notes=U)」を抽出するコマンド例です。

grep "notes=U" /var/log/dirsrv/slapd-localhost/access

これらのログから、「どのクライアントIPが」「どんなフィルタ条件で」検索しているかを特定し、必要なインデックスを追加するか、クライアント側のアプリ設定(検索フィルタ)を修正させます。


第6章:プロの現場から。トラブルシューティング事例集

実際に私が現場で遭遇したパフォーマンス問題とその解決策を紹介します。

Case 1: 部分一致検索の乱用

現象: 住所録アプリで検索するとサーバーCPUが100%になる。
原因: アプリが (cn=*tarou*) のような「前方一致」ではなく「中間一致」検索を投げており、cn 属性に sub インデックスが設定されていなかった。
対策: cn 属性に sub インデックスを追加し、Reindexを実施。CPU負荷は数%まで低下。

Case 2: 仮想環境でのIOPS不足

現象: キャッシュは足りているのに書き込みが遅い。
原因: 仮想化基盤のストレージが遅く、トランザクションログの書き込み(fsync)がボトルネックになっていた。
対策: トランザクションログのディレクトリ(/var/lib/dirsrv/.../db)を、高速なSSDストレージ領域に移動(シンボリックリンクまたはマウント)。

Case 3: VLV (Virtual List View) の負荷

現象: GUIの管理ツールでユーザー一覧を表示すると固まる。
原因: サーバー側ソートとページング(VLV)を行うためのインデックス(Browsing Index)が生成されていなかった。
対策: VLVインデックスを作成(設定が少し複雑なので、基本的には検索フィルタで絞り込む運用を推奨)。


まとめ:パフォーマンスは「設計」で決まる

お疲れ様でした!
第7回は、389 DSのパフォーマンスチューニングについて、インデックスとキャッシュを中心に解説しました。

今回の重要ポイント:

  • 遅延の最大の原因は「インデックス不足」による全件走査である。
  • ログの notes=Uetime を監視し、遅いクエリを特定する。
  • eq インデックスは必須。sub は必要に応じて追加する。
  • 物理メモリの50%程度を目安に、DBキャッシュとエントリキャッシュに配分する。
ウィンドウズ先生

サーバーのパフォーマンスは、ハードウェアを買えば解決するものではありません。
データの使われ方(検索クエリ)を知り、適切な索引(インデックス)を用意し、メモリ空間を有効活用する。
これこそがエンジニアの「技術力」です。
快適なレスポンスは、ユーザーへの最高のサービス提供になりますよ。

さて、サーバー側の設定はこれで完璧です。
最終回は、クライアント側の設定です。
LinuxサーバーからこのLDAPを使ってログインできるようにし、さらにホームディレクトリの自動作成なども行う統合環境を構築します。

次回、最終回(第8回)は「クライアント連携。SSSDによるオフライン認証と統合管理」です。
従来の nslcd に代わるモダンなクライアント SSSD の設定と、キャッシュによる耐障害性の向上について解説します。お楽しみに!

▼ チューニングの効果を測定する ▼

大量データを投入して検証
「おすすめVPS」

おすすめVPSを見る

DBA・パフォーマンスエンジニアへ
「ITエンジニア転職」

転職エージェントを見る

コメント