Azure SQL を使用して Azure Cloud Services 用に開発された Web アプリケーションがあります。1 つのデータベースから開始し、JMeter を使用して、同じ Azure データセンター内の専用仮想マシンから負荷テストを実行しました。テスト計画は、1 つのページのみをテストし、そのページへの投稿のみを行うように設定されました (最初の get 要求は無視されます)。
私の目標は、アプリが 1 秒間に処理できるデータベース トランザクションの最大数を決定することでした。私の最初の一連のテストでは、このテスト計画を使用して平均 300 リクエスト/秒という結果になりました。
問題のページは、次のテーブルにアクセスしています。
create table [dbo].[Entries]
(
[Id] int not null identity(1,1)
/* other columns here, about 10 in total */
);
alter table [dbo].[Entries] add constraint [PK_Entries] primary key ([Id]);
alter table [dbo].[Entries] add constraint [DF_Entries_Created] default(getutcdate()) for [Created];
create index [IX_Entries_EmailAddress] on [dbo].[Entries] ([EmailAddress]);
create index [IX_Entries_NACSZ] on [dbo].[Entries]
(
[FirstName]
,[LastName]
,[Address1]
,[City]
,[State]
,[Postal]
);
ページは次の 2 つのクエリのみを実行します。
select 1 where exists
(
select 1 from Entries
where EmailAddress = @EmailAddress
or (
FirstName = @FirstNAme
and LastName = @LastName
and Address1 = @Address1
and City = @City
and State = @State
and Postal = @Postal
)
);
と
insert into Entries
(
...
)
values
(
...
);
select cast(scope_identity() as int);
私のマシン (クアッド コア、8GB RAM、ローカル SQL 2012 Express インストール) でのパフォーマンス テストでは、最大 800 要求/秒が得られたので、Azure のサーバーで約 300 要求/秒のピークを見てかなりショックを受けました。これをデータベース サーバーでのリソースの競合に結びつけ、シャーディングをサポートするために必要なコードを追加しました。シャーディング メカニズムは、キー フィールドの 1 つで一貫したハッシュを使用して、使用する接続文字列を決定します (現在、3 つの可能性から)。ここでの目標は、データベースの負荷を 3 つの Azure SQL データベースに分割し、アプリの同時実行係数を上げることでした。
シャーディング メカニズムが機能することを確認し (最終的に各データベースにほぼ同数のエントリが作成される)、ページから不要なコードをすべて取り除き、上記の 2 つのクエリだけが実行されるようにしました。トランザクションでデフォルトの分離レベル (読み取りコミット) を使用しています。最終的なコードは次のようになります。
using (var db = ConnectToShard(keyToHash))
using (var tx = db.BeginTransaction(IsolationLevel.ReadCommitted))
{
// execute query 1
// if result from query 1 is null,
// execute query 2
tx.Commit();
}
ただし、この余分な作業をすべて行っても、リクエスト/秒を 500 程度以上にプッシュすることはできないようです。私の理想的な目標は 1000 です。Azure SQL のパフォーマンスに関して何かが欠けていると思いますが、それが何かはわかりません。リクエスト/秒を改善するための考えや提案はありますか?