2016-03-26 2 views
0

私はEntity Frameworkのパフォーマンスに非常に特有の問題があります。私はフレームワークのバージョン7をSQLiteプロバイダ(どちらもnuget製)で使用しています。データベースには約10百万のレコードがありますが、将来は約100百万個になります。 dbの構築は非常に簡単です:(Entity framework)Group by-lowパフォーマンス

public class Sample 
{ 
    public int SampleID { get; set; } 
    public long Time { get; set; } 
    public short Channel { get; set; } /* values from 0 to 8191, in the presented test 0-15 */ 
    public byte Events { get; set; } /* 1-255 */ 
} 

public class Channel 
{ 
    public int ChannelID { get; set; } 
    public short Ch { get; set; } 
    public int Es { get; set; } 
} 

public class MyContext : DbContext 
{ 
    // This property defines the table 
    public DbSet<Sample> Samples { get; set; } 
    public DbSet<Channel> Spectrum { get; set; } 

    // This method connects the context with the database 
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) 
    { 
     var connectionStringBuilder = new SqliteConnectionStringBuilder { DataSource = "E://database.db" }; 
     var connectionString = connectionStringBuilder.ToString(); 
     var connection = new SqliteConnection(connectionString); 

     optionsBuilder.UseSqlite(connection); 
    } 
} 

私はイベントをチャンネル別にグループ化し、スペクトルのようなものにしようとします。私はlinq2sqlを使用するとき、私は非常に低いパフォーマンスを持っています。 10mのレコードでは約15分かかり、1GBのRAMを取得してOutOfMemoryExceptionをスローします。Entity Frameworkはすべてのレコードをオブジェクトとしてメモリにロードしていると思いますが、なぜですか?一方、シンプルなSQLは約3秒を要し、大量のRAMを必要としません。

 using (var db = new MyContext()) 
     { 
      var res1 = from sample in db.Samples 
         group sample by sample.Channel into g 
         select new { Channel=g.Key, Events = g.Sum(s => s.Events) }; 
      res1.ToArray(); 

      var res2 = db.Natas.FromSql("SELECT Channel as ChannelID, Channel as Ch, SUM(Events) as Es FROM Sample GROUP BY Channel"); 
      var data = res2.ToArray(); 
     } 

助けてくれてありがとう;)

+0

なぜ「orderby」が必要ですか? –

+0

私はorder byを使って結果を適切な順序で取得します(グループ化してから使用してください)。この場合linqのこの部分を削除しても、パフォーマンスは変わりません。 質問のコードでOrderByの部分を削除して、より明確にしました。 –

+0

しかし、注文は "はるかに高速な純粋なSQL"ではありません。 SQLが機能的に同一でない限り、リンゴとオレンジを比較します。 – TomTom

答えて

1

提案しますか?エンティティフレームワークを無視する。

次のように:これはまったく面白くないEFの問題ではありません。

EFから送信されたSQLを調べ、そのレベルから最適化します。ああ、あなたはSQLにほとんど影響しません。このような簡単なステートメントの場合、SQLは最適になります。

最適ではないこと - SQLを見たことがないヒント - データベースです。そこに指標はありますか?コードはまず、データベースの複雑さに無知であり、あなたは「自分のデータベースが最適です」から最初にそれを見る必要があるという点で驚くべきものです。指数。そして - 悲しいことに - ハードウェア。 1億行に達した場合、これを処理するにはデータベースに力を持たせる必要があります。

私はエンティティフレームワークがすべてのレコードをオブジェクトとしてメモリにロードしていると思います - なぜですか?

パフォーマンスデベロッキングのルール1:考えないでください - チェックしてください。生成されたSQL(log、res1変数はあなたに表示されます)を見て、データベースに送信されるものを見てください。

多くのデータがある可能性があります。あなたは何チャンネルが存在するかについて何も言わない - これはもっと大きな機械を必要とするかもしれない。

を確認してください。

また、必要がない限り、結果を配列に取り込むことは本当にスマートではありません。配列はこのシナリオではメモリに問題があり(サイズを取得するための再割り当て)、LISTはより良い(より多くのメモリを使用しますが再割り当ては必要ありません)。しかし一般的には、結果セットを具体化することを避けたい、つまり、列挙可能なものから作業すること。必ずしもそうではありませんが、あなたのテストでは、その面で問題が簡単に見える場合があります結果として得られる配列は大変かもしれません。 1つのメモリが必要です。

真剣に、あなたのデータベース技術の選択に疑問を呈してください。 SqlLiteは素晴らしいです - それは小さく、軽量です。それは記憶にある。それは大量のデータには適していません。フルスケールのデータベースサーバーではありません。あなたはSql Expressを使用するほうがずっと良いかもしれません(SQL Expressはあなたのプロセスにはないが別のキャッシュにメモリを使います)。私は個人的に何億ものレコードを使用するかもしれない何かのためにSqlLiteを使用しません。

また、SQLが異なることに注意してください。 EFパートにはOrderBy(これは不要です)、SQLではありません。注文は高価かもしれません。これは、「エンティティフレームワークによって生成されたSQLを取得する」ことに戻ります。

+0

生成されたSQLをチェックしようとしました。残念ながら、実際のバージョンのEFには、SQLiteプロバイダを使用しているときにSQLを表示する際にいくつかの問題があります。だから私はそれをチェックする能力がない。私はVisual StudioのRAM使用量のグラフを見て、使用量がまだ上がっていることを確認します。 私は、単一ファイル(SQLite)とバイナリファイルのデータベースの間で簡単な選択肢があります。私の経験では、dbは私の解決策ではなくエンジンによって最適化されると言いました。プログラムは物理実験で使用され、ソリューションは単一ファイルでなければならないという要件があります。 –

+0

クエリの結果には8192までの行があります(テストされたシナリオでは16しかありません)。 orderby文は影響を与えません(チェックされています)。すべてのデータはチャートを生成するために使用されるため、遅延ロードのためのスペースはありません。 –

+1

それは問題を残します。そのようなものについては、EFを使用しないことを検討してください。良い選択肢はLinq2DBで、これは「半ORM」です。それはLINQマッピングには多くの - そしてより良い - sqlを行いますが、それ以上の機能はありません。それは超高速であることを報告するのに最適です。 SqlLiteの問題がある可能性があります。次のステップとして、メモリのプロファイラを使用してメモリがどこに失われているかを確認することをお勧めします。そして、ToList THEN ToArrayを作成してみてください。これは、メモリの制約の下で、より効率的(サイズ変更なし)になる可能性があります。 – TomTom

-1

問題はSQLiteプロバイダに接続されました。 SQL Server Compactへの変更後は正常に動作します;

+0

この回答には、行われた変更の詳細な説明が必要です。 – Gusdor

関連する問題