データベースの設計とパフォーマンス (SQL Server Compact)
SQL Server Compact 3.5 アプリケーションのパフォーマンスは、SQL Server のデータベースとパブリケーションを正しく設計することで大幅に向上できます。以下のセクションでは、パフォーマンスの向上に使用できる手法の概要を説明します。
データベースの非正規化の使用
正規化されたデータベースは、データが機能上の依存関係を持たず、データベースの更新を容易かつ効率的に行えるようになっています。ただし、データベースに対してクエリを実行する際、情報を結合するために多くのテーブルを結合することが必要になる場合があります。結合テーブルの数が増加するにつれて、クエリの実行時間は長くなります。そのため、正規化されたデータベースが最善の選択肢とはいえない場合があります。適度に非正規化したデータベースを使用すると、結合するテーブルの数を減らすことができます。その際の更新処理はそれほど複雑ではありません。これが適切な代替案になる場合が数多くあります。
注意
通常、多数のクエリで 5 個または 6 個以上のテーブルを結合する必要がある場合は、非正規化を検討してください。
データベースの非正規化には他の種類もあります。たとえば、データベースに Orders および Order Details という 2 個のテーブルがあるとします。Orders テーブルには、顧客の注文に関する情報が含まれています。各注文の個別の商品は Order Details テーブルに含まれています。各注文の合計金額をクエリしてみましょう。まず、各商品の金額を特定する必要があります (個数 x 単価 – 適用可能な割引額で算出できます)。その後、注文ごとに金額をまとめる必要があります。以下に、使用するクエリを示します。
SELECT "Order ID", SUM("Unit Price" * Quantity * (1.0 - Discount))
AS Total FROM "Order Details"
GROUP BY "Order ID"
Order ID Total
----------------------------------------
10000 108
10001 1363.15000915527
10002 731.800003051758
10003 498.180023193359
10004 3194.19999694824
10005 173.400009155273
10006 87.2000007629395
10007 1405
10008 1171
10009 1530
10010 470
... ...
(1078 rows affected)
このクエリの計算は慎重に行う必要があります。大口の注文では、クエリの実行に長時間かかります。この代替策として、注文が行われた時点で注文の金額を計算し、Orders テーブル内の列にその金額を格納しておくことができます。このアプローチを使用する場合、計算前の列に対してのみクエリを実行し、必要な情報を返す必要があります。これを行うには次のようなステートメントを使用します。
SELECT "Order ID", "Order Total" AS Total FROM Orders
計算前の列を作成することにより、クエリ時間を大幅に縮小することができますが、このアプローチではテーブル内に別の列を保持することが必要になります。
可変長列または固定長列の選択
テーブルの設計時には、可変長列と固定長列の用途の違いを理解しておくと役立ちます。可変長列は、実際の値を格納するために必要なものだけを使用するので、データベース サイズが減少します。固定長列は、実際の値が空の場合でも、スキーマによって定義された最大領域を常に格納します。可変長列の欠点は、演算によっては固定長列での演算ほど効率的ではないものがあることです。たとえば、可変長列のサイズが最初は小さく、UPDATE により大幅にサイズが増加すると、レコードの再配置が必要になる場合があります。さらに、その後の更新処理により、データ ページが長期にわたってより多くの断片に分割されます。そのため、データのサイズがほとんど変わらない場合と更新の実行頻度が高い場合は、固定長列を使用することをお勧めします。
サイズが小さい行の作成
ページに保持できる行の数は、各行の最適化方法によって異なります。行のサイズが小さいほど、ページにはより多くの行を保持できます。そのため、最適化した行を持つテーブルで 1 つのディスク操作を行うと、複数の行を取得でき、操作がより効率的になります。さらに、複数の行がストレージ エンジンのキャッシュに含まれるので、ヒット率が高くなる可能性があります。また、行を最適化すると、データ ページ上の不要な領域が削除されます。サイズが大きな行では、不要な領域がよく生じます。
これに関する極端な例について考えて見ましょう。レコードのサイズがデータ ページの半分より若干大きい場合、各データ ページの領域の約半分は不要になります。データベース設計者によっては、広大なテーブルを設計し、メインフレームのデータベース スキーマをデバイスに移植する場合があります。これは効率的な設計とはいえません。考えられるアプローチの 1 つは、最も重要なテーブルを分割することです。ほとんど変化しない値と頻繁に変化する値を持つ列がいくつか含まれているテーブルがあるとします。その場合、テーブルを 2 つに分割するのが合理的です。1 つは頻繁に参照される列を含むテーブルで、もう 1 つは変化しない列を含むテーブルです。2 つのテーブルを作成することにより、行のサイズが小さくなるという利点があります。欠点としては、情報を組み合わせるための結合処理が必要になります。
サイズが小さいキーの使用
インデックスは、作成先のテーブルの順序付けされたサブセットです。インデックスにより、高速な範囲照合と並べ替え順序が許可されます。インデックス キーが小さいほど、使用する領域が少なくなり、大きなキーよりも効率的になります。主キーは他のテーブル内の外部キーとして頻繁に参照されるので、主キーを最適化するのは特に効果的な方策です。元から最適化されている主キーがない場合は、整数型として実装されている ID 列を代わりに使用できます。
1 つまたは少数のキー列しか含まないインデックスは、狭いインデックスと呼ばれます。多くのキー列を持つインデックスは、広いインデックスと呼ばれます。広いインデックスは、サイズの大きいキーに関連付けられていることがよくあります。この極端な例は、テーブル内の各列がインデックスに含まれる場合です。このようなインデックスを作成すると、元のテーブルの複製が効率的に作成されますが、これは、データベースのサイズとクエリのパフォーマンスの点から見ると効率的ではありません。
パブリケーション アーティクルの種類とオプション
SQL Server 2008 R2 でパブリケーションを作成する場合、パブリケーションのアーティクルで 2 つのオプションを選択できます。これらの選択肢は、以下に示すとおり、フィルタ処理、およびパブリッシャとサブスクライバ間のデータの移動を制御するものです。
ダウンロード専用 (読み取り専用)
スマート デバイス上に保持するデータが参照テーブルのみに格納することが必要な状況があるとします。たとえば、ユーザーがスマート デバイス上の会社の従業員名簿を参照する必要があり、その一方でこの情報を編集したり変更したりすることはできないようにする必要がある場合です。ダウンロード専用のアーティクルの種類は、このような用途に向いています。ダウンロード専用のアーティクルは、デバイス上にメタデータが格納されないのでサイズが小さくなります。そのため、同期中のネットワーク トラフィックが減少します。
適切なパーティション分割
SQL Server 2008 R2 で適切にパーティション分割されたアーティクルを使用すると、アップロードする変更は 1 つのパーティション ID のみにマップされます。このマッピングはより高速ですが、以下のようにいくつかの制限事項があります。
アーティクル内の各行は、1 つのパーティション ID のみに属している必要があります。
各アーティクルは、1 つのパブリケーションのみにパブリッシュできます。
サブスクライバは、パーティション ID に属していない行を挿入することはできません。
適切にパーティション分割されたアーティクルの使用時には、フィルタ処理も影響を受けます。以下の制限事項がフィルタ処理に適用されます。
サブスクライバはフィルタ処理に関連する列を更新できません。
結合フィルタ階層では、標準のアーティクルを適切にパーティション分割されたアーティクルにできません。
適切にパーティション分割されたアーティクルが子である結合フィルタでは、join_unique_key を値 1 に設定しておく必要があります。
各アーティクルは、1 つのサブセットまたは 1 つの結合フィルタのみを持つことができます。アーティクルにはサブセット フィルタを含めて、アーティクルを結合フィルタの親にすることができますが、サブセット フィルタを含めて、結合フィルタの子にすることはできません。