[英]EF Core and MySql query is too slow
我在 mysql 中有 2 個名為市場和交易所的表。
交換表中大約有 150 萬條記錄。
我想從交易所表中獲取每個市場最高更新日期的記錄。 作為查詢的結果,我想返回一個列表,其中每個市場只有一個最近的更新。
我使用 linq 創建了如下查詢。 但他的反應非常緩慢。
大約 7-8 分鍾。 我該如何解決這個問題?
感謝您的回答。
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();
市場實體類;
[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; }
}
交易所實體類;
[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; }
}
查詢很慢,因為它使用了當前不受支持的結構,這會導致客戶端評估。 大數據的客戶端評估效率很低,這也是EF Core 3.0 中將其刪除的原因之一。
所以訣竅是找到支持的 LINQ 構造(轉換為 SQL 並執行服務器端)。 由於每個 EF Core 版本都支持不同的結構,我不能確切地說 2.0 支持哪一個,但在最新的 2.2 中,一般來說,請嘗試遵循以下簡單規則:
GroupBy
。並始終檢查客戶評估警告。 在 3.0+ 中,無論如何它們都會是運行時異常,所以你必須找到一個可翻譯的結構。
以下是一些在 2.2.6 中工作的功能等效的 LINQ 查詢:
(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) 與 (1) 相同,但使用!Any
(SQL NOT EXISTS
) 條件:
where !market.Exchanges.Any(e => e.LastUpdatedDateTime < exchange.LastUpdatedDateTime)
(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.