实体框架Mysql慢查询

时间:2018-08-15 09:04:22

标签: mysql entity-framework

在我的数据库中,我有3个主要的类别,即育种者,马匹和种族。这3个表具有多对多关系。一个饲养员可以有多匹马,一匹马可以有多个饲养员。一匹马也可以参加多个比赛,而一个比赛中可以有多个马参加。现在,我想查询一个种鸽的比赛统计数据。使用实体框架,我有以下代码行:

var races = DbContext.HorseBreeders
            .Where(w => w.BreederId == someint)
            .SelectMany(s => s.Horse.Races)
            .ToList();

并且此代码生成以下mysql查询:

        SELECT `w.Horse.Races`.`Id`, `w.Horse.Races`.`FinishTime`, `w.Horse.Races`.`Horse_Id`, `w.Horse.Races`.`Race_Id`
        FROM `HorseBreeders` AS `w`
        INNER JOIN `Horses` AS `w.Horse` ON `w`.`HorseId` = `w.Horse`.`Id`
        INNER JOIN `RaceEntries` AS `w.Horse.Races` ON `w.Horse`.`Id` = `w.Horse.Races`.`Horse_Id`
        WHERE `w`.`BreederId` = someint

此查询大约需要30秒。

  • Breeders表具有13000条记录
  • 马表有6万条记录
  • HorseBreeders表具有4万条记录
  • 种族表有11万条记录
  • RaceEntries表具有960k记录。

在Mssql中,具有类似查询的相同结构花了不到一秒钟的时间。但是在Mysql中,它花费了太多时间。我在做什么错了?

DbContext类:

public class Breeder
{
    public int Id { get; set; }

    [StringLength(50)]
    public string Name { get; set; }

    public virtual ICollection<HorseBreeder> Horses { get; set; }
}

public class Horse
{
    public int Id { get; set; }

    [StringLength(50)]
    public string Name { get; set; }

    public int? Father_Id { get; set; }
    public virtual Horse Father { get; set; }

    public int? Mother_Id { get; set; }
    public virtual Horse Mother { get; set; }

    public string BirthPlace { get; set; }
    public DateTime? BirthDate { get; set; }

    public virtual ICollection<HorseBreeder> Breeders { get; set; }

    public virtual ICollection<RaceEntry> Races { get; set; }

    public virtual ICollection<Horse> FatherChilds { get; set; }
    public virtual ICollection<Horse> MotherChilds { get; set; }
}

public class HorseBreeder
{
    public int HorseId { get; set; }
    public Horse Horse { get; set; }
    public int BreederId { get; set; }
    public Breeder Breeder { get; set; }
}

public class Race
{
    public int Id { get; set; }

    public DateTime Time { get; set; }
    public string Name { get; set; }

    public virtual ICollection<RaceEntry> Horses { get; set; }
}

public class RaceEntry
{
    public int Id { get; set; }

    public int Race_Id { get; set; }
    public virtual Race Race { get; set; }

    public int Horse_Id { get; set; }
    public virtual Horse Horse { get; set; }

    public short? FinishTime { get; set; }
}

DbContext OnModelCreating:

protected override void OnModelCreating(ModelBuilder builder)
{
    base.OnModelCreating(builder);

    // Horse
    builder.Entity<HorseBreeder>()
                .HasKey(bc => new { bc.HorseId, bc.BreederId });

    builder.Entity<HorseBreeder>()
        .HasOne(bc => bc.Horse)
        .WithMany(b => b.Breeders)
        .HasForeignKey(bc => bc.HorseId);

    builder.Entity<HorseBreeder>()
        .HasOne(bc => bc.Breeder)
        .WithMany(c => c.Horses)
        .HasForeignKey(bc => bc.BreederId);

    builder.Entity<Horse>()
                .HasOne(p => p.Father)
                .WithMany(p => p.FatherChilds)
                .HasForeignKey(p => p.Father_Id);

    builder.Entity<Horse>()
                .HasOne(p => p.Mother)
                .WithMany(p => p.MotherChilds)
                .HasForeignKey(p => p.Mother_Id);

    // RaceEntry
    builder.Entity<RaceEntry>()
                .HasOne(m => m.Race)
                .WithMany(t => t.Horses)
                .HasForeignKey(m => m.Race_Id);

    builder.Entity<RaceEntry>()
                .HasOne(m => m.Horse)
                .WithMany(t => t.Races)
                .HasForeignKey(m => m.Horse_Id);
}

数据库创建迁移:

public partial class initial_create : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.CreateTable(
            name: "Breeders",
            columns: table => new
            {
                Id = table.Column<int>(nullable: false)
                    .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
                Name = table.Column<string>(maxLength: 50, nullable: true)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_Breeders", x => x.Id);
            });

        migrationBuilder.CreateTable(
            name: "Horses",
            columns: table => new
            {
                Id = table.Column<int>(nullable: false)
                    .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
                Name = table.Column<string>(maxLength: 50, nullable: true),
                Father_Id = table.Column<int>(nullable: true),
                Mother_Id = table.Column<int>(nullable: true),
                BirthPlace = table.Column<string>(nullable: true),
                BirthDate = table.Column<DateTime>(nullable: true)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_Horses", x => x.Id);
                table.ForeignKey(
                    name: "FK_Horses_Horses_Father_Id",
                    column: x => x.Father_Id,
                    principalTable: "Horses",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Restrict);
                table.ForeignKey(
                    name: "FK_Horses_Horses_Mother_Id",
                    column: x => x.Mother_Id,
                    principalTable: "Horses",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Restrict);
            });

        migrationBuilder.CreateTable(
            name: "Races",
            columns: table => new
            {
                Id = table.Column<int>(nullable: false)
                    .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
                Time = table.Column<DateTime>(nullable: false),
                Name = table.Column<string>(nullable: true)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_Races", x => x.Id);
            });

        migrationBuilder.CreateTable(
            name: "HorseBreeders",
            columns: table => new
            {
                HorseId = table.Column<int>(nullable: false),
                BreederId = table.Column<int>(nullable: false)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_HorseBreeders", x => new { x.HorseId, x.BreederId });
                table.ForeignKey(
                    name: "FK_HorseBreeders_Breeders_BreederId",
                    column: x => x.BreederId,
                    principalTable: "Breeders",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Cascade);
                table.ForeignKey(
                    name: "FK_HorseBreeders_Horses_HorseId",
                    column: x => x.HorseId,
                    principalTable: "Horses",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Cascade);
            });

        migrationBuilder.CreateTable(
            name: "RaceEntries",
            columns: table => new
            {
                Id = table.Column<int>(nullable: false)
                    .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
                Race_Id = table.Column<int>(nullable: false),
                Horse_Id = table.Column<int>(nullable: false),
                FinishTime = table.Column<short>(nullable: true)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_RaceEntries", x => x.Id);
                table.ForeignKey(
                    name: "FK_RaceEntries_Horses_Horse_Id",
                    column: x => x.Horse_Id,
                    principalTable: "Horses",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Cascade);
                table.ForeignKey(
                    name: "FK_RaceEntries_Races_Race_Id",
                    column: x => x.Race_Id,
                    principalTable: "Races",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Cascade);
            });

        migrationBuilder.CreateIndex(
            name: "IX_HorseBreeders_BreederId",
            table: "HorseBreeders",
            column: "BreederId");

        migrationBuilder.CreateIndex(
            name: "IX_Horses_Father_Id",
            table: "Horses",
            column: "Father_Id");

        migrationBuilder.CreateIndex(
            name: "IX_Horses_Mother_Id",
            table: "Horses",
            column: "Mother_Id");

        migrationBuilder.CreateIndex(
            name: "IX_RaceEntries_Horse_Id",
            table: "RaceEntries",
            column: "Horse_Id");

        migrationBuilder.CreateIndex(
            name: "IX_RaceEntries_Race_Id",
            table: "RaceEntries",
            column: "Race_Id");
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropTable(
            name: "HorseBreeders");

        migrationBuilder.DropTable(
            name: "RaceEntries");

        migrationBuilder.DropTable(
            name: "Breeders");

        migrationBuilder.DropTable(
            name: "Horses");

        migrationBuilder.DropTable(
            name: "Races");
    }
}

0 个答案:

没有答案