SQL に関する Q&Aデータベースのサイズ、ミラーリング、マーク付きトランザクション、その他

Nancy Michell 編

クラスタの移動

Q SQL Server 2000 クラスタを新しい IP アドレスに移行しなければなりません。Windows® クラスタおよび SQL Server™ クラスタの IP アドレスだけでなく、それを支える物理的なサーバーの IP アドレスも移行する必要があります。ソリューション全体を再構築する必要がありますか。

A いいえ、SQL Server のセットアップを実行して IP アドレスを変更するだけで済みます。その方法を説明するサポート技術情報の記事を参照してください。

データベースのサイズ

Q 私は SQL Server 2000 SP4 を業務用に使用しています。これは、ほぼ 10GB のミッション クリティカルなデータベース、単純復旧モデル、9,850MB のプライマリ ファイル、88MB のトランザクション ログ ファイルによって構成されています。データベースのバックアップもほぼ 10GB です。パフォーマンスの向上にはデータベースのサイズを縮小すべきでしょうか。その場合、DBCC SHRINKDATABASE を使用すべきでしょうか DBCC SHRINKFILE を使用すべきでしょうか (残念ながら、このメンテナンスを非ピーク時に行うことはできません)。

A DBCC SHRINKDATABASE も DBCC SHRINKFILE もデータベースで多数の削除や更新が行われ、データのボリュームが小さくなった場合にしか役立ちません。でも、真の問題はなぜそれを問題にするのかということです。10GB のディスク容量は今では 20 ドルぐらいです。100GB のデスク領域を追加して稼動させた方がいいと思いませんか。パフォーマンスは領域が断片化してくると劣化します。メンテナンスができないとすれば、選択肢は限られています。このようなケースではデータベースの第 2 のコピーを使用する人もいます。リプリケーションを使用してバックアップ コピーを常に最新の状態に更新しておき、メンテナンスをバックアップ コピーに対して行った後、アプリケーションをバックアップに切り替えることができます。この方法では明らかに、いくつかコードを変更して、単純復旧モデルから完全または一括ログ モデルに変更する必要があります。

アップグレードとパフォーマンス

Q SQL Server 2000 から SQL Server 2005 へ 2 つのアプリケーションを移行しなければなりません。このアップグレード中にパフォーマンスへの影響を避ける方法はありますか。

A 通常、次の落とし穴がアップグレードによるパフォーマンス劣化の原因になりますから、避けるようにしてください。

  1. SQL Server 2005 にアップグレードした後、統計を再構築していない。
  2. 2 つの異なったデータ型を比較する JOINS と WHERE 句があり、それが原因でパフォーマンスが悪くなっている。特にサーバーが SQL Server 2000 SP3 以前のバージョンを実行していた場合 (support.microsoft.com/kb/271566/ を参照)。
  3. SQL Server 2005 インスタンスが正しく構成されていない。メモリ、Address Windowing Extensions (AWE)、ドライバなどの構成が間違っている。SQL Server 2000 を実行しているコンピュータを調整した人が、その記録を残さずに去った。そして、その調整は SQL Server 2005 インスタンスに対して行われなかった。
  4. ハードウェアに問題がある。新しいハードウェアがよさそうに見えたので購入したが、実際には期待通りに機能していないということがよくある。

SQL Server インスタンスを実稼動に投入する前に、パフォーマンス ベースラインを確立して期待通りのパフォーマンスが得られることを確認する必要があります。それによってインフラストラクチャが問題である可能性を除外できます。ディスク、I/O、メモリなどの Perfmon カウンタを見て、インスタンス間で比較する必要があります。

データベース ミラーリング

Q データベース ミラーリングを使用していますが、READ_COMMITTED_SNAPSHOT データベース オプションを有効にするにはどうしたら良いですか。ミラーリングをセットアップした後で有効にしようとしたのですが、データベースがミラーリング セッションに入っているという意味のエラーが出て、そのコマンドを実行できませんでした。

A エラーになったのは READ_COMMITTED_SNAPSHOT オプションの設定を有効にするにはデータベースを再起動する必要があるからです。したがって、ミラーリング セッションを停止して、問題のオプションを設定し、データベースを再起動する必要があります。ミラーリングはこの手順を完了した後に再開できます。ミラー データーベースはセッションが再開されるとそのオプションを採用し、フェールオーバー時に使用します。

Q 非同期ミラーリングをセットアップしようとしたのですが 1418 エラーが出ます。Netstat -ano を実行すると SQL Server はすべてのサーバーで正しいポートをリッスンしていることがわかります。エラーはミラーリングを開始しようとすると出ます。どうなっているのでしょうか。

A ファイアウォールによって通信がブロックされている可能性があります。これは比較的よくあることなので調べる必要があります。詳細については、技術白書のデータベース ミラーリングの設定のトラブルシューティング および MSSQLSERVER_1418 を参照してください。

この問題は非同期ミラーリングに特有の問題ではないことに注意してください。実際、同期ミラーリングでも発生する問題です。

ご覧になったエラーは「The server network address "%.*ls" cannot be reached or does not exist. Check the network address name and reissue the command (サーバーのネットワーク アドレス "%.*ls" に到達できないか、存在しないアドレスです。ネットワーク アドレスを確認してコマンドを再実行してください)」だったと思いますが、そのとおりです。多くの場合、リモートのサーバーが存在しないのではなくて、単に到達できなくなっているだけです。

これは、リモート サーバーがダウンしているとき、ポートをリッスンしていないとき、またはエンドポイントがダウンしているときでも発生します。エンドポイントのダウンは、相手のサーバーが同じ暗号化機能をネゴシエートできないときやその他の認証問題がある場合に発生します。相手のサーバーがブロックされている場合もあります。これはコマンドを開始する相手のサーバー上のファイアウォールが原因になっている可能性があります。

その他に確認すべき問題としては、データ ソース名 (DSN) と名前解決の問題があります。通常は、完全修飾ドメイン名の使用を推奨します。多くの場合ファイアウォールが問題の原因になっていますが、他にもいろいろ原因がありうることも知っておいてください。

Q SQL Server 2005 ミラーリングを使用したいのですが、複数のアプリケーションが同じ SQL Server インスタンス上の複数のデータベースに接続している場合にはミラーリングは推奨されていないと聞きました。本当ですか。

A 答えは各アプリケーションが別々のデータベースを持っているか、複数のアプリケーションが複数のデータベースを参照しているか、分散トランザクション コーディネータ (DTC) トランザクションが使用されているかに依存します。複数データベースにまたがるトランザクションが使用されている場合、ミラーリングによって論理的な不整合が発生し、期待通りにトランザクションがコミットされなくなります。このような条件下で何が起こるかのわかりやすい説明は、ここにあります

複数のデータベースと複数のアプリケーションが使用されていても、個々のアプリケーションが独自のデータベースを持っている場合は、ミラーリングがそのような問題の原因となることはありません。

マーク付きトランザクション

Q マーク付きトランザクションというのはどんなものですか。それは 1 つのデータベースが SQL Server で、もう 1 つが Oracle というような場合に使用できるものですか。

A トランザクションにマークを付ける作業は、すべてのログの中の同じ場所にマークを付けるために DBA が定期的に行う作業です。この作業は、データベースをトランザクション マークまで復元する機能を使用して、すべてのデータベースを同じところまで復旧できるようにするためのものです。これはかなり苦痛を伴う作業です。関連のすべてのデータベースを復元する必要があり、すべてのデータベースでデータが失われます。それを避けるには、ログ ファイルが失われないようにする必要があります。マーク付きトランザクションは SQL Server 独特のものです。分散トランザクションに SQL Server 以外のデータベースも含まれている場合、それらはトランザクションのマーク付けに参加できません。一般に、分散データベース システムでトランザクション マークが使用されることはめったにありません。トランザクション ログの消失は、復旧に多大の手作業を必要とする致命的なイベントとして扱われます。

Access から T-SQL への変換ツール

Q ストアド プロシージャ用の Access™-SQL から T-SQL への自動変換ツールはありますか。

A SQL Server Migration Assistant (SSMA) for Access を試してください。これは (英語) からダウンロードできます。そこには SQL Server Migration Assistant for Oracle、SQL Server Migration Assistant for Sybase、および Migrating Informix Databases to Microsoft® SQL Server 2000 もあります。

Access から SQL Server にアップサイズするには、Office アップサイジング ウィザードを使用できますが、図 1 に示した SSMA for Access の方が変換評価レポートやネットワーク スキャンなどのより充実した機能を備えています。SSMA for Access は Office アップサイジング ウィザードでは現在適切に処理されない多くの問題を処理できます。

図 1 SQL Server Migration Assistant for Access

図 1** SQL Server Migration Assistant for Access **(画像を拡大するには、ここをクリックします)

非クラスタ化インデックス

Q プライマリ キーが 2 つの GUID (GUID1 と GUID2) からなるテーブルがあります。GUID1 と GUID2 上には一意のクラスタ化インデックスが既にありました。今、パフォーマンス上の理由で、第 2 の非クラスタ化インデックスを GUID2 と GUID1 上に作成しようと考えていますが、インデックスを一意にするとパフォーマンスに影響するようなオーバーヘッドが発生しますか。

A 非クラスタ化インデックスを一意と宣言することによってパフォーマンスが低下することはありません。それどころか、そうすることによってインデックス ツリーのレベル数が減少する可能性があります。

非クラスタ化インデックスを一意と宣言すると、ルートと非リーフ ページでその行ロケータがインデックス エントリのキーの末尾に追加されます。これはインデックス エントリの削除や更新を促進するために行われるもので、キーが重複して存在する場合に同義チェーンのスキャンを避けます。変更対象のエントリはシステム シーク処理をキーとロケータの両方に対して行うことで検索できます。その結果、選択したクラスタ キーによってそれらのエントリはかなり長くなります。したがって、ルートと非リーフ ページがいっぱいになるのも速くなります。インデックスが一意の場合、それを宣言すべきです。

要するに、テーブルにクラスタ化インデックスがあるかどうかにかかわらず、そのデーブルの非クラスタ化インデックスが一意と宣言されていない場合、ルートとその他の非リーフ ページにおいてロケータがインデックス エントリに追加されるのです。

さらに、int 識別子列を代理キーとして使用し、次に 2 つの一意のインデックス (GUID1、GUID2) と (GUID2、GUID1) を追加する場合、インデックスは 32 バイトのクラスタリング キーではなく 4 バイトのクラスタリング キーになるためパフォーマンスが向上する可能性があります。

ロックの更新

Q 次のような構造のストアド プロシージャがあります。

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION

-- Get The lock if available
UPDATE    ProcessingInstances 
SET       LockHolder = @MessageId
WHERE     ( InstanceId = @InstanceId ) 
AND       ( LockHolder IS NULL )

COMMIT TRANSACTION

このストアド プロシージャはロックを 1 つの呼び出しにしか渡さないので、他の呼び出しは待たされます。同じ動作を分離レベルを低くすることによって達成できますか。

READ COMMITTED が適切な分離レベルのように見えます。なぜなら、このトランザクションには 1 つのクエリしかありません。別のトランザクションが同じレコードを更新中の場合、このトランザクションはその別のトランザクションを待つことになります。これは正しいですか。

A 他の呼び出しを待たせているのはシリアル化可能の設定ではありません。それは更新処理自体です。確かに、分離は READ COMMITTED に設定しておくことができます。当然、更新処理は使用するインデックスの更新ロックを取ります。これは、同じステートメントを実行している別のプロセスに問題を引き起こすので、その更新が終わるまでブロックされます (更新が唯一のステートメントなら、ここでは明示的なトランザクションは必要ありません。各ステートメントは、明示的なトランザクションでなければ、暗黙に独立したトランザクションです)。

UPDATE ステートメントの中の WHERE 句に一致する行がない場合、シリアル化可能な分離レベルを使用することによって、そのような行が別のトランザクションによって挿入されたり変更されたりしないようにできます。UPDATE を READ COMMITTED 分離で実行すると、そうはなりません。別のトランザクションがその更新に適合する行を挿入できます。ストアド プロシージャ コードが、見せていただいたコードのようになっている場合、シリアル化やトランザクションなどの操作を行っても意味がありません。単純に更新を実行してください。

**次の Microsoft IT 技術支援スタッフに心より感謝します。**Gaurav Aggarwal、Anthony Bloesch、Todd Briley、Shaun Cox、Roberto Di Pietro、Michael Epprecht、Kevin Farlee、Umachandar Jayachandran、Chuck Ladd、Kaloian Manassiev、Luciano Moreira、Ward Pond、Mark Prazak、Arunachalam Thirupathi、Roger Wolter、Clement Yip、Frankie Yuen。

© 2008 Microsoft Corporation and CMP Media, LLC. All rights reserved; 許可なしに一部または全体を複製することは禁止されています.