简体   繁体   English

EF Core 和 MySql 查询太慢

[英]EF Core and MySql query is too slow

I have 2 tables named markets and exchanges in mysql.我在 mysql 中有 2 个名为市场和交易所的表。
There are approximately 1.5 million records in the exchanges table.交换表中大约有 150 万条记录。
I would like to get records from exchanges table with the highest update date of each market.我想从交易所表中获取每个市场最高更新日期的记录。 As a result of the query, I want to return a list with only one recent update for each market.作为查询的结果,我想返回一个列表,其中每个市场只有一个最近的更新。
I created a query like the following with linq.我使用 linq 创建了如下查询。 But he responds very slowly.但他的反应非常缓慢。
Approximately 7-8 minutes.大约 7-8 分钟。 How do I fix this problem?我该如何解决这个问题?

Thanks for your answers.感谢您的回答。

var query = (from exchange in _context.Exchanges
             join market in _context.Markets on exchange.MarketId equals market.Id
             where market.TypeId == 1
             group exchange by exchange.MarketId into grp

             let maxdate = grp.Max(x => x.LastUpdatedDateTime)

             from exchanges in grp
             where exchanges.LastUpdatedDateTime == maxdate
             select new DtoGetAllMarketsWithLastExchanges
             {
                 Id = exchanges.MarketId,
                 Code = exchanges.Markets.Code,
                 Name = exchanges.Markets.Name,
                 LastBuyPrice = exchanges.LastBuyPrice,
                 LastSellPrice = exchanges.LastSellPrice,
                 SeoUrl = exchanges.Markets.SeoUrl,
                 Icon = exchanges.Markets.Icon,
                 LastUpdateDate = exchanges.LastUpdatedDateTime,
                 Rate = exchanges.Rate
             }).ToList();

Markets Entity Class;市场实体类;

[Table("Markets")]
public partial class Markets : BaseEntity
{
    public int TypeId { get; set; }

    public string Code { get; set; }

    public string Name { get; set; }

    public byte Unit { get; set; }

    public int OrderNumber { get; set; }

    public string Icon { get; set; }

    public string SeoUrl { get; set; }

    public virtual List<Exchanges> Exchanges { get; set; }
}

Exchanges Entity Class;交易所实体类;

[Table("Exchanges")]
public partial class Exchanges : BaseEntity
{
    public int MarketId { get; set; }

    public double LastBuyPrice { get; set; }

    public double LastSellPrice { get; set; }

    public double Rate { get; set; }

    public DateTime CreatedDateTime { get; set; }

    public DateTime LastUpdatedDateTime { get; set; }

    [ForeignKey("MarketId")]
    public virtual Markets Markets { get; set; } 

}

The query is slow because it uses currently unsupported constructs which cause client evaluation .查询很慢,因为它使用了当前不受支持的结构,这会导致客户端评估 Client evaluation is quite inefficient with big data, which is one of the reasons it will be removed in EF Core 3.0 .大数据的客户端评估效率很低,这也是EF Core 3.0 中将其删除的原因之一。

So the trick is to find LINQ construct which is supported (translated to SQL and executed server side).所以诀窍是找到支持的 LINQ 构造(转换为 SQL 并执行服务器端)。 Since every EF Core version supports different constructs, I can't say exactly which one is supported in 2.0, but in latest 2.2 and in general, try following the next simple rules:由于每个 EF Core 版本都支持不同的结构,我不能确切地说 2.0 支持哪一个,但在最新的 2.2 中,一般来说,请尝试遵循以下简单规则:

  • Use navigation properties over manual joins where possible尽可能在手动连接上使用导航属性
  • Avoid GroupBy where possible.尽可能避免使用GroupBy

And always check for client evaluation warnings.并始终检查客户评估警告。 In 3.0+ they will be runtime exceptions anyway, so you have to find a translatable construct.在 3.0+ 中,无论如何它们都会是运行时异常,所以你必须找到一个可翻译的结构。

Here are some of the functionally equivalent LINQ queries which work in 2.2.6:以下是一些在 2.2.6 中工作的功能等效的 LINQ 查询:

(1) With Max criteria (1) 使用Max标准

from market in _context.Markets
where market.TypeId == 1
from exchange in market.Exchanges
where exchange.LastUpdatedDateTime == market.Exchanges.Max(e => (DateTime?)e.LastUpdatedDateTime)
select new DtoGetAllMarketsWithLastExchanges
{
    Id = market.Id,
    Code = market.Code,
    Name = market.Name,
    LastBuyPrice = exchange.LastBuyPrice,
    LastSellPrice = exchange.LastSellPrice,
    SeoUrl = market.SeoUrl,
    Icon = market.Icon,
    LastUpdateDate = exchange.LastUpdatedDateTime,
    Rate = exchange.Rate
}

(2) Same as (1), but with !Any (SQL NOT EXISTS ) criteria: (2) 与 (1) 相同,但使用!Any (SQL NOT EXISTS ) 条件:

where !market.Exchanges.Any(e => e.LastUpdatedDateTime < exchange.LastUpdatedDateTime)

(3) Same as (1), but with join to Max subquery: (3) 与 (1) 相同,但join Max子查询:

from market in _context.Markets
where market.TypeId == 1
from exchange in market.Exchanges
join lastExchange in _context.Exchanges
    .GroupBy(e => e.MarketId)
    .Select(g => new { MarketId = g.Key, Date = g.Max(e => e.LastUpdatedDateTime) })
on new { exchange.MarketId, Date = exchange.LastUpdatedDateTime }
equals new { lastExchange.MarketId, lastExchange.Date }
select new DtoGetAllMarketsWithLastExchanges
{
    Id = market.Id,
    Code = market.Code,
    Name = market.Name,
    LastBuyPrice = exchange.LastBuyPrice,
    LastSellPrice = exchange.LastSellPrice,
    SeoUrl = market.SeoUrl,
    Icon = market.Icon,
    LastUpdateDate = exchange.LastUpdatedDateTime,
    Rate = exchange.Rate
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM