我遇到了具有大量继承类的 LINQ to SQL 模型的性能问题。
我隔离了这个问题,它似乎是 LINQ to SQL 生成的代码本身的某种问题。
我使用 Northwind 创建了一个示例程序来充实这个问题。在这两种情况下,它都会返回 Customer 的第一行。数据库查询很简单,运行时间
在“小型”场景中,它有 4 种类型,其中一种基本 Customer 类型和三种使用 LINQ 继承的派生类型。
在“大型”场景中,它具有 60 多种类型(包含一个基本 Customer)和 60 多种使用 LINQ 继承和 INT 列鉴别器的派生类型。
与第一个(超过 2 秒)相比,大型数据上下文的性能很糟糕,即使它是相同的查询和返回的相同数据。
这是输出。
Performance Comparison of LINQ to SQL
Run each 3 times in a row for cache
With 4 Inherited Tables
00:00:00.2340004 of Small Test for First Customer:A Bike Store
00:00:00 of Small Test for First Customer:A Bike Store
00:00:00 of Small Test for First Customer:A Bike Store
With >60 Inherited Tables
00:00:01.7004030 of Large TestFirst Customer:A Bike Store
00:00:00.0156000 of Large TestFirst Customer:A Bike Store
00:00:00.0156001 of Large TestFirst Customer:A Bike Store
With 4 Inherited Tables
00:00:00 of Small Test for First Customer:A Bike Store
00:00:00 of Small Test for First Customer:A Bike Store
00:00:00 of Small Test for First Customer:A Bike Store
With >60 Inherited Tables
00:00:00.0156000 of Large TestFirst Customer:A Bike Store
00:00:00.0156000 of Large TestFirst Customer:A Bike Store
00:00:00.0156001 of Large TestFirst Customer:A Bike Store
Press Any Key
请注意,第一次运行 LARGE 数据集需要 1.7 秒与 0.23 秒(慢 7 倍)
即使第二组运行速度较慢,但性能还是可以接受的。
这是完整的应用程序可供下载http://cid-02bee16e84f5c99f.office.live.com/self.aspx/Public/TestDalLinqPerformance.zip
从我们的调试来看,这与生成的代码有关:
[global::System.Data.Linq.Mapping.InheritanceMappingAttribute(Code="2", Type=typeof(Customer2))]
[global::System.Data.Linq.Mapping.InheritanceMappingAttribute(Code="67", Type=typeof(Customer67))]
[global::System.Data.Linq.Mapping.InheritanceMappingAttribute(Code="65", Type=typeof(Customer65))]
[global::System.Data.Linq.Mapping.InheritanceMappingAttribute(Code="615", Type=typeof(Customer615))]
[global::System.Data.Linq.Mapping.InheritanceMappingAttribute(Code="513", Type=typeof(Customer613))]
public partial class Customer : INotifyPropertyChanging, INotifyPropertyChanged
当使用 40 多个表继承生成时,这个值很大,并且与 LINQ 2 SQL 类相比速度较慢。我们还验证了这与“InheritanceDiscriminator”有关,因为如果删除它,性能就很好。
后续调用速度很快,并且似乎在线程本地存储中缓存了一些东西。有没有办法在多个线程中持久化它?