2012-01-24 8 views
1

大きなプロジェクトでは、Linq2SqlをWebサービス(WCF)で使用することに決めました。一部のデータが追加された後(小さなコンソールアプリから顧客データをインポートした後)、ウェブサービスはそのアプリの存続期間中は鈍化していたことがすぐに分かりました。少し遅れてLinq2Sqlが遅くなる

アプリを再起動するたびに、最初はデータが高速にインポートされてから、10〜15分の読み込み後に速度が低下しました。

私は、メインアプリの小さな部分を模倣したサンプルアプリを作成しようとしました。私は追加する必要が

  • 、私たちは、誰もがこのアプリの減速何についての手掛かりを持っていますかなどreqular SqlCommandオブジェクト/ SqlConnectionオブジェクトに置き換えるWebサービスでLinq2Sqlを除外する

を決めましたによって引き起こされる可能性がありますか?

は、ここではいくつかのデータベースクエリを模倣する「最小化」アプリのコードです:

のAppを含むSQL文は、テーブルを作成するために:あなたは、単一のデータ・コンテキストを使用している

using System; 
using System.Collections.Generic; 
using System.Linq; 

using System.Text; 

namespace Linq2SqlTest 
{ 
    class Program 
    { 
     /* 
     * USE [Linq2SqlTest] 
      GO 
      SET ANSI_NULLS ON 
      GO 
      SET QUOTED_IDENTIFIER ON 
      GO 
      CREATE TABLE [dbo].[Adresse](
       [id] [int] IDENTITY(1,1) NOT NULL, 
       [person_id] [int] NOT NULL, 
       [Gate] [nvarchar](50) NOT NULL, 
       [Poststed] [nvarchar](50) NOT NULL, 
       [By] [nvarchar](50) NOT NULL, 
      CONSTRAINT [PK_Adresse] PRIMARY KEY CLUSTERED 
      (
       [id] ASC 
      )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
      ) ON [PRIMARY] 

      GO 
      ALTER TABLE [dbo].[Adresse] WITH CHECK ADD CONSTRAINT [FK_Adresse_Person1] FOREIGN KEY([person_id]) 
      REFERENCES [dbo].[Person] ([id]) 
      GO 
      ALTER TABLE [dbo].[Adresse] CHECK CONSTRAINT [FK_Adresse_Person1] 
     * 
     * 
     * USE [Linq2SqlTest] 
      GO 
      SET ANSI_NULLS ON 
      GO 
      SET QUOTED_IDENTIFIER ON 
      GO 
      CREATE TABLE [dbo].[Items](
       [ItemID] [int] IDENTITY(1,1) NOT NULL, 
       [ItemNumber] [nchar](10) NOT NULL, 
       [PersonID] [int] NOT NULL, 
       [name] [nvarchar](50) NULL, 
      CONSTRAINT [PK_Items] PRIMARY KEY CLUSTERED 
      (
       [ItemID] ASC 
      )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
      ) ON [PRIMARY] 

      GO 
      ALTER TABLE [dbo].[Items] WITH CHECK ADD CONSTRAINT [FK_Items_Person] FOREIGN KEY([PersonID]) 
      REFERENCES [dbo].[Person] ([id]) 
      GO 
      ALTER TABLE [dbo].[Items] CHECK CONSTRAINT [FK_Items_Person] 

     * 
     * USE [Linq2SqlTest] 
       GO 
       SET ANSI_NULLS ON 
       GO 
       SET QUOTED_IDENTIFIER ON 
       GO 
       CREATE TABLE [dbo].[Person](
        [id] [int] IDENTITY(1,1) NOT NULL, 
        [name] [nvarchar](50) NOT NULL, 
        [AddedDate] [datetime] NOT NULL, 
        [ssn] [nvarchar](50) NOT NULL, 
       CONSTRAINT [PK_Person] PRIMARY KEY CLUSTERED 
       (
        [id] ASC 
       )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
       ) ON [PRIMARY] 

     */ 

     public static Random randomizer = new Random(); 

     public static String GenerateName() 
     { 
      int nLetterCount = (randomizer.Next() % 5) + 3; 

      String s = ""; 
      for (int i = 0; i < nLetterCount;i++) 
      { 
       int r = (randomizer.Next() % 26)+97; 
       s += Convert.ToChar(r); 
      } 
      return s; 
     } 
     public static String GenerateFullname() 
     { 
      String Fullname = ""; 
      int nNameCount = randomizer.Next() % 3; 
      nNameCount++; 
      while (nNameCount>0) 
      { 
       if (Fullname.Length == 0) 
        Fullname = GenerateName(); 
       else 
        Fullname += " " + GenerateName(); 
       nNameCount--; 
      } 
      return Fullname; 
     } 
     static void Main(string[] args) 
     { 
      DatabaseDataContext db = new DatabaseDataContext(); 

      for (int i = 0; i < 300000;i++) 
      { 
       int personid = randomizer.Next() % 100; 
       Person p = db.Persons.FirstOrDefault(_p=> _p.ssn == personid.ToString()); 
       if (p == null) 
       { 
        p = new Person(); 
        p.name = GenerateFullname(); 
        p.ssn = personid.ToString(); 
        p.AddedDate = DateTime.Now; 
        db.Persons.InsertOnSubmit(p); 
        db.SubmitChanges(); 
        Adresse a = new Adresse(); 
        a.person_id = p.id; 
        a.Gate = GenerateFullname(); 
        a.Poststed = GenerateName(); 
        a.By = GenerateName(); 
        db.Adresses.InsertOnSubmit(a); 
        db.SubmitChanges(); 
        int jj = randomizer.Next() % 10 + 1; 
        for (int j = 0; j < jj; j++) 
        { 
         Item item = new Item(); 
         item.ItemNumber = randomizer.Next().ToString(); 
         item.PersonID = p.id; 
         db.Items.InsertOnSubmit(item); 
         db.SubmitChanges(); 
        } 
       } 
       else 
       { 
        int jj = randomizer.Next() % 10 + 1; 
        for (int j = 0; j < jj; j++) 
        { 
         int number = randomizer.Next(); 
         Item item = db.Items.FirstOrDefault(_i => _i.ItemNumber == number.ToString()); 
         if (item == null) 
         { 
          item = new Item(); 
          item.ItemNumber = number.ToString(); 
          item.PersonID = p.id; 
          db.Items.InsertOnSubmit(item); 
         } 
         else 
         { 
          item.ItemNumber = randomizer.Next().ToString(); 
         } 
         db.SubmitChanges(); 
        } 
       } 
       Console.WriteLine("\r" + i + " "); 
      } 
     } 
    } 
} 
+0

どのくらい減速していますか?ここにスケールのアイディアを与えるために、実行時間の印刷物がありますか? – Servy

+0

ANTS Profilerなどのアプリをプロファイリングしようとしたことがありますか? – Xaisoft

+0

@Servy:サンプリングを行うために1つのアプリ(偽の顧客データなど)でデータ転送を行いましたが、当初は約6000人の顧客を抱えていました。 5分後には1分に1500人の顧客になり、10分後には約150人の顧客になりました。 – OddBeck

答えて

0

をチェックしてみてください。データのいくつかはすでに「プリロードされています」(遅延読み込み?)、これは無効にされていませんでした。したがって、LINQが何をすべきかを制御し、 "背後にいない"場合は、この機能を無効にする必要があります。

DatabaseContext.DeferredLoadingEnabled = false; 

ルーキーミス、悲しいことに: - |

2

。データコンテキストが含まれています:

  • アイデンティティマネージャー
  • あなたが触れる複数のオブジェクト、太っそれを取得を意味変更トラッカ

。それがより広がるほど、毎回行う作業が増えます。そしてそれは遅くなる。

データコンテキストを必要以上に長くしないでください。例えば、作業単位は、しっかりと小さくて慎重な単位でなければなりません。

THEN L2SはIDisposableを実装しているので、あなたも、あなたが使用して各データ・コンテキストを破棄確保すべき新た

を開始します。

+0

ええ、この場合、私は単一のdatacontextを使用するので、私は会社のアプリの初めにやりました。しかし、物事をちょっと読んだあと、必要以上にデータコンテキストを使用すべきではないことがわかったので、データコンテキストを必要に応じて作成するように変更しました。 IE: ブールAddNewItemToPerson(項目項目、人の人物) { 使用(DBContextデシベル=新しいDBContext()) { // //クラブのメンバーシップを確認するか、追加存在する人物を確認するか、それを追加すること //既存の項目を確認するか追加する db.SubmitChanges(); } } – OddBeck

0

私が取り組んでいるアプリでも同様の現象が見られます。私の場合、原因はSQLサーバーによる非常に大きなメモリ消費です。

同様の設定(クライアント、SQLサーバー、ビジュアルスタジオを持つ1台のマシン)で実行している場合は、コンピュータ上のメモリ使用量を見てください(プロセスエクスプローラ、仮想サイズ列を追加して並べ替えます)。あなたが減速と仮想サイズの間の相関を見ている場合 - >あなたのコンピュータをより多くのRAMに処理するか、または不要なプロセスをクリーンアップします。

ところで、データコンテキストに関する回答があなたのケースに関連する場合は、まずその問題を解決してください。

+0

アプリは会社のアプリケーションのデータベースに接続していますが、メモリは問題ではありません。もう1人の共同作業者は、 "dbContext.SubmitChanges()"を極端に遅くしようとは思わないかもしれないと提案しましたが、これまでLinq2Sqlを放棄して純粋なSqlcommandsを使用してきました。 Linq2Sqlはコードを書くのが非常に簡単なので、それは罪です。 – OddBeck

0

Linq2SQl関数を呼び出すときに、コンパイルされたLINQ文を使用して1つまたはいくつかの項目しか返さないときに、大きな改善が見られました。

詳細については、私は問題を解決する方法を見つけたこの記事http://www.foliotek.com/devblog/unexpected-benefits-of-precompilation-of-linq/

+0

ええ、私もそれを見ましたが、私はlinqをかなり使用しているので、多くのプリコンパイルがあり、別の方法と明白なコーディングエラーがあることを期待しています。もちろん、pplにコードがないので何が間違っていると言うのは難しいです。 – OddBeck

+0

ええ、私は、常に単一のオブジェクトまたはオブジェクトの小さなリストを返すlinq文をプリコンパイルすると言うでしょう。私はこれを行うことによって巨大なパフォーマンスの向上を見たことがありますが、コードはプリコンパイルされたステートメントのために非常に醜いですが、それは私の唯一の苦情です。 – bigamil

関連する問題