2016-10-31 27 views
4

私のEFクエリは、10人のプレーヤーをフェッチするのに約3秒かかります。なぜなら、必要な数ではなく、他のテーブルの500k +行すべてをフェッチするからです。エンティティフレームワーク1対多の関係

これはPlayerEntityです:

namespace RocketLeagueStats.Database.Entities 
{ 
    [Table("players", Schema = "public")] 
    public class PlayerEntity 
    { 

     [Key] 
     [Column("id")] 
     public int Id { get; set; } 

     [Column("unique_id")] 
     public string UniqueId { get; set; } 

     [Column("display_name")] 
     public string DiplayName { get; set; } 

     [Column("platform_id")] 
     [JsonIgnore] 
     public int PlatformId { get; set; } 

     [ForeignKey("PlatformId")] 
     public PlatformEntity Platform { get; set; } 

     [Column("avatar")] 
     public string Avatar { get; set; } 

     public PlayerStatsEntity Stats { get; set; } 

     public List<PlayerRankedEntity> Ranks { get; set; } 

     [Column("last_requested")] 
     public DateTime LastRequested { get; set; } 

     [Column("created_at")] 
     public DateTime CreatedAt { get; set; } 

     [Column("updated_at")] 
     public DateTime UpdatedAt { get; set; } 

    } 
} 

これはPlayerRankedEntityです:

namespace RocketLeagueStats.Database.Entities 
{ 
    [Table("player_ranked", Schema = "public")] 
    public class PlayerRankedEntity 
    { 

     [ForeignKey("Player")] 
     [Column("player_id")] 
     [JsonIgnore] 
     public int PlayerId { get; set; } 

     [Column("season_id")] 
     [JsonIgnore] 
     public int SeasonId { get; set; } 

     [Column("playlist_id")] 
     [JsonIgnore] 
     public int PlaylistId { get; set; } 

     [Column("matches_played")] 
     public int MatchesPlayed { get; set; } 

     [Column("rank_points")] 
     public int RankPoints { get; set; } 

     [Column("tier")] 
     public int Tier { get; set; } 

     [Column("division")] 
     public int Division { get; set; } 

     public PlayerEntity Player { get; set; } 

    } 
} 

これはPlayerStatsEntityです:

namespace RocketLeagueStats.Database.Entities 
{ 
    [Table("player_stats", Schema = "public")] 
    public class PlayerStatsEntity 
    { 

     [Key, ForeignKey("Player")] 
     [Column("player_id")] 
     [JsonIgnore] 
     public int PlayerId { get; set; } 

     [Column("wins")] 
     public int Wins { get; set; } 

     [Column("goals")] 
     public int Goals { get; set; } 

     [Column("mvps")] 
     public int Mvps { get; set; } 

     [Column("saves")] 
     public int Saves { get; set; } 

     [Column("shots")] 
     public int Shots { get; set; } 

     [Column("assists")] 
     public int Assists { get; set; } 

     public PlayerEntity Player { get; set; } 

    } 
} 

これは私のDatabaseContext.OnModelCreating方法である:

protected override void OnModelCreating(ModelBuilder modelBuilder) 
{ 
    modelBuilder.Entity<PlayerRankedEntity>() 
     .HasKey(k => new { k.PlayerId, k.SeasonId, k.PlaylistId }); 
} 

これが完了するまでに3秒以上を要するコード(私は削除する場合は「.INCLUDE(X => x.Ranks)」を、それはほんの数ミリ秒かかります)です。これは、出力され

using (var database = new DatabaseContext()) 
{ 
    var serviceProvider = database.GetInfrastructure(); 
    var loggerFactory = serviceProvider.GetService<ILoggerFactory>(); 
    loggerFactory.AddNLog(); 

    var stopwatch = Stopwatch.StartNew(); 

    var players = database.Players 
     .Include(x => x.Ranks) 
     .Take(10) 
     .ToArray(); 

    Console.WriteLine($"Took {stopwatch.ElapsedMilliseconds}ms to fetch {players.Length} players"); 
} 

、それは代わりに1の2つのクエリを生成していることに気づく:

2016-10-31 22:50:18.6416 INFO Executed DbCommand (8ms) [Parameters=[@__p_0='?'], CommandType='Text', CommandTimeout='30'] 
SELECT "x"."id", "x"."avatar", "x"."created_at", "x"."display_name", "x"."last_requested", "x"."platform_id", "x"."unique_id", "x"."updated_at" 
FROM "public"."players" AS "x" 
ORDER BY "x"."id" 
LIMIT @__p_0 
2016-10-31 22:50:18.7128 INFO Executed DbCommand (0ms) [Parameters=[@__p_0='?'], CommandType='Text', CommandTimeout='30'] 
SELECT "p"."player_id", "p"."season_id", "p"."playlist_id", "p"."division", "p"."matches_played", "p"."rank_points", "p"."tier" 
FROM "public"."player_ranked" AS "p" 
WHERE EXISTS (
    SELECT 1 
    FROM "public"."players" AS "x" 
    WHERE "p"."player_id" = "x"."id" 
    LIMIT @__p_0) 
ORDER BY "p"."player_id" 
Took 3991ms to fetch 10 players 

私はそれがすべての行を選択させる、どこか関係に台無しだと思います。しかし、私は何を台無しにしたのか分からない。

どうすればこの問題を解決できますか?自分の属性に他の問題はありますか?

私はMicrosoft.EntityFrameworkCore v1.0.1を使用しています。

編集: または.Where(x => x.DiplayName.Contains("mike"))をクエリに使用すると、処理時間が大幅に短縮されます。

生成されたクエリ:

2016-11-01 00:14:15.9638 INFO Executed DbCommand (24ms) [Parameters=[@__p_0='?'], CommandType='Text', CommandTimeout='30'] 
SELECT "x"."id", "x"."avatar", "x"."created_at", "x"."display_name", "x"."last_requested", "x"."platform_id", "x"."unique_id", "x"."updated_at" 
FROM "public"."players" AS "x" 
ORDER BY "x"."created_at", "x"."id" 
LIMIT @__p_0 
2016-11-01 00:14:16.0972 INFO Executed DbCommand (44ms) [Parameters=[@__p_0='?'], CommandType='Text', CommandTimeout='30'] 
SELECT "p"."player_id", "p"."season_id", "p"."playlist_id", "p"."division", "p"."matches_played", "p"."rank_points", "p"."tier" 
FROM "public"."player_ranked" AS "p" 
INNER JOIN (
    SELECT DISTINCT "x"."created_at", "x"."id" 
    FROM "public"."players" AS "x" 
    ORDER BY "x"."created_at", "x"."id" 
    LIMIT @__p_0 
) AS "x0" ON "p"."player_id" = "x0"."id" 
ORDER BY "x0"."created_at", "x0"."id" 
Took 314ms to fetch 10 players 
+0

EFコア地獄へようこそ:(わずか10人のプレイヤー(LIMIT句の両方)をロードしているようですが? –

+0

:)トラッキングモードを無効にして、役立つかどうか確認してください – CodeNotFound

+0

実際に2番目のクエリは間違っています - EXITTS'と 'LIMIT'、何? –

答えて

1

EFコアは現在、悪夢です。

次の回避策を試すことができます(ただし、私に聞いた場合は、EF6に戻ってください)。

var players = database.Players 
    .Include(x => x.Ranks) 
    .Take(10) 
    .ToArray(); 

使用:代わりの

Includeと同じ効果をもたらすべき

var players = database.Players 
    .Take(10) 
    .ToArray(); 
var playerIds = players.Select(p => p.Id); 
database.PlayerRanks.Where(r => playerIds.Contains(r.PlayerId)).Load(); 

+0

これは約3000ms〜約120msの時間を短縮しました。これはかなり良い結果です。私はnetstandard 1.6を使用しなければならないので、私はEF6に行くことができません。これはランクでWHEREを使用する機能を削除しないでしょうか? – AeonLucid

+0

こんにちは@イワンStoev EFコアチームはこれらの問題について知っていますか? – Sampath

+0

@Sampathこんにちは、彼らは確かに。彼らのGitHubに行くと、それは問題がいっぱいです:) –

関連する問題