how Query Notifications workを読むと、単一のクエリテンプレートを使用して多数の依存関係リクエストを作成するのが適切な理由がわかります。 であり、SqlDependency
ではないことが暗示されているウェブアプリの場合、何をする予定はOKです。あなたがLinq2Sqlを使用する場合もLinqToCacheを試すことができます。
ファットクライアントアプリケーションのために
var queryUsers = from u in repository.Users
where u.UserId = currentUserId
select u;
var user= queryUsers .AsCached("Users:" + currentUserId.ToString());
それはOKではないでしょう。ではないので、それ自体は、クエリのが、一般的にSqlDependency
ので、接続しているクライアントの数が多い(そのブロック接続アプリケーションドメインあたりa worker thread)との問題がある:をASPで使用されるように設計された
SqlDependency。 NETまたは中間層 サービスは、データベースに対してアクティブである の依存関係を持つ比較的少数のサーバーが存在するサービスです。数百または数千のクライアント コンピュータで、単一の データベースサーバーに対してSqlDependencyオブジェクトが設定されているクライアントアプリケーションでは、 を使用するようには設計されていませんでした。ここで
を更新しました
@usrは彼のポストで行ったように同じテストです。完全なC#コード:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using DependencyMassTest.Properties;
using System.Threading.Tasks;
using System.Threading;
namespace DependencyMassTest
{
class Program
{
static volatile int goal = 50000;
static volatile int running = 0;
static volatile int notified = 0;
static int workers = 50;
static SqlConnectionStringBuilder scsb;
static AutoResetEvent done = new AutoResetEvent(false);
static void Main(string[] args)
{
scsb = new SqlConnectionStringBuilder(Settings.Default.ConnString);
scsb.AsynchronousProcessing = true;
scsb.Pooling = true;
try
{
SqlDependency.Start(scsb.ConnectionString);
using (var conn = new SqlConnection(scsb.ConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(@"
if object_id('SqlDependencyTest') is not null
drop table SqlDependencyTest
create table SqlDependencyTest (
ID int not null identity,
SomeValue nvarchar(400),
primary key(ID)
)
", conn))
{
cmd.ExecuteNonQuery();
}
}
for (int i = 0; i < workers; ++i)
{
Task.Factory.StartNew(
() =>
{
RunTask();
});
}
done.WaitOne();
Console.WriteLine("All dependencies subscribed. Waiting...");
Console.ReadKey();
}
catch (Exception e)
{
Console.Error.WriteLine(e);
}
finally
{
SqlDependency.Stop(scsb.ConnectionString);
}
}
static void RunTask()
{
Random rand = new Random();
SqlConnection conn = new SqlConnection(scsb.ConnectionString);
conn.Open();
SqlCommand cmd = new SqlCommand(
@"select SomeValue
from dbo.SqlDependencyTest
where ID = @id", conn);
cmd.Parameters.AddWithValue("@id", rand.Next(50000));
SqlDependency dep = new SqlDependency(cmd);
dep.OnChange += new OnChangeEventHandler((ob, qnArgs) =>
{
Console.WriteLine("Notified {3}: Info:{0}, Source:{1}, Type:{2}", qnArgs.Info, qnArgs.Source, qnArgs.Type, Interlocked.Increment(ref notified));
});
cmd.BeginExecuteReader(
(ar) =>
{
try
{
int crt = Interlocked.Increment(ref running);
if (crt % 1000 == 0)
{
Console.WriteLine("{0} running...", crt);
}
using (SqlDataReader rdr = cmd.EndExecuteReader(ar))
{
while (rdr.Read())
{
}
}
}
catch (Exception e)
{
Console.Error.WriteLine(e.Message);
}
finally
{
conn.Close();
int left = Interlocked.Decrement(ref goal);
if (0 == left)
{
done.Set();
}
else if (left > 0)
{
RunTask();
}
}
}, null);
}
}
}
50Kサブスクリプションは、ここで、(約5分かかります)に設定された後の統計は、単一のインサートのioのです:1000行を挿入
set statistics time on
insert into Test..SqlDependencyTest (SomeValue) values ('Foo');
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 0 ms.
SQL Server Execution Times:
CPU time = 16 ms, elapsed time = 16 ms.
は約7秒かかり、これ数百の通知を発します。 CPU使用率は約11%です。これは私のT420s ThinkPadにあります。
set nocount on;
go
begin transaction
go
insert into Test..SqlDependencyTest (SomeValue) values ('Foo');
go 1000
commit
go
私は、接続されていないユーザーであっても、そのユーザーデータをすべてキャッシュするのは大変だと思います。 –
SqlCacheDependencyにはキャッシュエビクションポリシーがあります。 –
これは基本的に私のテストで示されたのと同じパフォーマンス結果です。依存関係の作成はマルチスレッド化されているため、より高速です。おそらく4倍になるでしょうか? 1000個のインサートの7sは*恐ろしい*です。 100%で11%cpu = 1コア。 – usr