先日、とある受託開発で開発したC/S型のシステムを、エンドユーザの運用環境にデプロイした時に発生したトラブルと、その解決に至った経緯の話です。
この記事に出てくる技術要素:SQLServer (データ移行/パフォーマンスチューニング)、仮想環境のメモリ割り当て
システム構成
そのシステムは以下の図のような構成となっていました。
ローカルネットワーク内にサーバとクライアントが配置される、典型的なC/S型のシステム構成です。 (※実際はもう少し複雑で、アプリケーションをClickOnceで配布したり、サーバ上でいくつかのサービスが実行されていたりしますが、今回の内容には関係ないので省略しています。)
サーバは複数のシステムが動いているようで、それぞれに仮想サーバが割り当てられています。今回のシステムもサーバ上に新しく仮想サーバを用意してもらい、そこにデプロイしました。
トラブル発生:システムの応答速度が異常に遅い
事前に社内で同一構成の検証環境を用意して、デプロイのリハーサルと動作確認を行いました。その時には何事もなく、システムも正常に稼働していたのですが…
デプロイ作業当日、運用環境へのサーバセットアップは順調に進んでいました。ほぼ見積通りの時間でデータの配置を終え、いざ導通確認。ということでクライアントからアプリケーションを起動してみたところ…
アプリケーションの動作が全体的に重い。
使い物にならないレベルで待たされます。何故..と思いながら調査を進めた結果、どうやらクライアントからサーバ上のデータベースに接続し、SQLコマンドを実行するタイミングで待たされることが分かってきました。
原因1. SQL Server インデックスの断片化?
システム上で実行されるSQLコマンドの大半はSELECT文なので、テーブルにインデックスが張られていないことも一瞬疑いましたが、確認したところインデックス自体は張ってありました。いよいよ当てがなくなってきたな…と悩んでいたら、トラブルについて相談していた上長から以下のSQLコマンドを実行してみるようにと指示が。
ALTER INDEX ALL ON {table_name} REBUILD;
インデックスの再構築コマンドです。これを実行してみたところ、コマンドの実行時間が1/5になり、目に見えて速度が改善されました。ということは、インデックスの断片化が進んでいたのでしょうか。
今回、運用環境へのデータ配置において、SQLServerデータベースは、別の環境で構築したデータベースをデタッチ&アタッチで移行することで配置したのですが、この作業で断片化が進むという情報がMicrosoftのフォーラムでも確認されました。なので、データ移行でSQLServerのパフォーマンスが落ちた時にはインデックスの再構築を行う意味はありそうです。
原因2. 仮想サーバへの動的メモリ割り当ての罠
上記のインデックス再構築を行い、アプリケーションの動作速度は確かに改善されたのですが、数十秒が数秒になったレベル。検証時は一瞬で応答を返していたので、まだ本来の速度とは言えません。どうすればいいのか悩んでいたら連絡が入りました。
サーバのメモリに余裕はある?
メモリ…作業開始時に仮想サーバには8GB(ハードウェア仕様として提示)がちゃんと割り当てられていることを確認したはず、と思いつつタスクマネージャを確認すると
おかしいですね。メモリ使用量は2.0GBですが、使用率は80%を超えているようにみえます。よく見ると「ハードウェア予約済み:6.0GB」と示されています。この仮想サーバ、実質2GBのメモリで動いているっぽい…?
結論をいうと、仮想化環境(おそらくHyper-V)の動的メモリ割り当て機能により、仮想サーバに割り当てられたメモリが必要最低限となっていたようです。先方のシステム担当の方にメモリの割り当てを8GBで固定して頂いたところ、アプリケーションの動作が本来の速度に戻り、問題を全て解消することができました。
所感
これまで何度かユーザの運用環境へのデプロイ作業を経験してきましたが、データベースのパフォーマンスに影響するトラブルに遭遇するのは初めてであったため戸惑ってしまいました。ただ、このようなケースでは何を確認するべきか、学びを得られました。