EfCore3的OwnedType會致使Sql效率問題

最近主導了旗下某核心項目升級到EfCore3git

因爲以前Core2升級時候也踩過很多的坑不少東西都有規劃和準備,總體上仍是沒出太大問題github

 

可是最近忽然發現efcore對於使用了ownedType的生成語句有問題併發

查找了一下資料發現已經有人在efcore的github上開了issus了,而且還討論的蠻多的了性能

https://github.com/dotnet/efcore/issues/18299  測試

 

鑑於不少人看到一堆E文後會直接放棄,下面我簡單闡述下這個問題

EfCore自2.0的時候引入了一個叫OwnedType的特性,是用於完善以前EfCore1.x相比於Ef6使其少了的ComplexType特性ui

正常來講咱們用Ef的時候是一個類映射到一個表,可是有時候某些表字段過多的狀況下,咱們可能會想整理下把一個表裏某些信息放到一個子類裏,可是其餘信息仍是在主類blog

 

形如get

class Order
{
    public int Id { get; set; }
    public string Title { get; set; }
    public Address Address { get; set; }
}

class Address
{
    public string Street { get; set; }
    public string City { get; set; }
}
 
而後DbContext裏配置下  
modelBuilder.Entity<Order>().OwnsOne(x => x.Address);  
 
這種狀況下最理想生成的語句應該是相似  
select Id,Title,Street,City from Orders
 這個樣子的形式纔對,而後EfCore內部再經過本身映射的形式把後面4個字段映射到Author類裏的Address這個類裏
 
可是在EfCore3裏他生成的語句是形如  
SELECT o."Id", o."Title", t."Id", t."Address_City", t."Address_Street"
      FROM "Orders" AS o
      LEFT JOIN (
          SELECT o0."Id", o0."Address_City", o0."Address_Street", o1."Id" AS "Id0"
          FROM "Orders" AS o0
          INNER JOIN "Orders" AS o1 ON o0."Id" = o1."Id"
          WHERE (o0."Address_Street" IS NOT NULL) OR (o0."Address_City" IS NOT NULL)
      ) AS t ON o."Id" = t."Id"
      WHERE (t."Id" IS NULL)

儘管嚴格來講這個並不影響邏輯,可是這樣子join的話對Sql的性能和效率有挺很差的負面影響string

就那個issus裏也有人作了測試,結果下圖it

image

縱座標是每秒執行的查詢數(簡單理解爲併發數吧)

橫座標是表裏有多少數據

能夠看到表的數據量上升以後使用了OwnedType的EfCore3會出現顯著下滑(本身join本身多了)

 

另外該問題在EfCore2的時候是沒有的,就Core3纔有(直覺是Core3的OwnedType被魔改了能夠支持OwnsMany等的支持的時候引入的)

 

接下來就是一個好消息和一個壞消息了

好消息是EfCore那邊承認了這個問題而後當前EfCore 5 preview-3修復了這個問題

 

壞消息是至少目前確認這個修復不會合併到EfCore3.1.x(後期會不會有變數不清楚)

 

感受這個蠻坑的,通常公司用的話都會是優先選用LTS,而當前的LTS就是3.1

而接下來的NetCore5(含EfCore5)並非LTS因此對於公司組織的線上採用率應該會相對較低

那難道修復這個問題還要等一個目前還沒規劃的NetCore5.1?那是否是要等的有點兒過久了

 

最後,若是有升級EfCore3的且用了OwnedType(至關於Ef6時期的ComplexType)請謹慎評估下這個問題對你可能形成的影響

畢竟目前看起來,降級回去不大可能,燒香保佑下fix path能到3.1.x要麼就只能期望Core5.1了

相關文章
相關標籤/搜索