Open Closed

ABP InsertManyAsync extremely slow with many thousands of entities #8152


User avatar
0
Baytech created
  • ABP Framework version: v8.3.0
  • UI Type: Angular
  • Database System: EF Core - PostgreSQL
  • Tiered (for MVC) or Auth Server Separated (for Angular): auth separated
  • Steps to reproduce the issue: Have 100k-200k entities, maybe 10 different entity types total. Call await _repo.InsertManyAsync(entities) for each entity type. It becomes very slow (30+ min) just on that InsertManyAsync call, not even saving changes yet. Bulk insert is not an option because it is paid, and EF should be able to handle that many easily - it is ABP that is slowing it down.

For what it's worth, I dug through ABP source code to find the culprit. It is on the PublishEntityCreatedEvent that gets called for every tracked entity in the AbpDbContext class. That eventually calls the AddOrReplaceEvent on the UnitOfWork class which does this: eventRecords.FindIndex(replacementSelector); where replacementSelector is defined as otherRecord => IsSameEntityEventRecord(eventRecord, otherRecord) in the EntityChangeEventHelper. That eventually gets to EntityHelper's EntityEquals(IEntity? entity1, IEntity? entity2) which uses a ton of reflection.

So for every new entity being tracked, it runs that equality reflection code for however many records have been inserted so far - the new tracked entity will never be in there, because it is new. So if I insert 200k entities, on the next entity added it runs through 200k entities to see if it needs to replace or add. The next entity after that it needs to do it 200,001 times. It gets exponentially slower, and it's very prohibitive. For what it's worth, I ended up fixing it by overriding the AbpDbContext and NOT publishing that tracked event for those entity types (ConnectWiseEntity is a base class I have for all 10 types) like so:

After that change, my bulk insert code went from 30-40 min to only 15 seconds.

I'd like to see 2 solutions here: make the local event publishing configurable like the distributed event publishing, AND fix the performance issue.

This is the code that does it in the EntityChangeEventHelper:

It runs the local event no matter what. Make that configurable like the distributed events below it.


No answer yet!
Made with ❤️ on ABP v9.1.0-preview. Updated on October 22, 2024, 09:35