- ABP Framework version: v5.3.3
- UI type: Angular
- DB provider: EF Core
- Tiered (MVC) or Identity Server Separated (Angular): no
- Exception message and stack trace:
- Steps to reproduce the issue:"
We are creating a support account, under every tenant and we are linking these accounts each other. Now we have aproximately 50 tenant and when we open Linked Accounts modal, it takes 30 seconds. This is really slow, if the number exceeds user gets timeout (so we removed some records to be able to open Linkend Accounts screen). I realised this endpoints gets whole records, not only selected page's records and also 50 records is not too much to take 30 seconds. I think there is a problem.
17 Answer(s)
-
0
-
0
Hi @alper did you try on your environment? Which indices you have on AbpLinkUsers or any related table? And why getting all records on a paged page, shouldn't it fetch 10 records for paged page?
-
0
@gizem can you pls test this case?
-
0
Hi @gizem
Did you able to test?
-
0
I'm checking, I'll report the situation.
-
0
-
0
hi @enes,
in our tests, it loads very fast. but as I see, your DB fetch is much slower than our tests. I created an internal issue to improve this modal. we will make server-side paging on this modal and I hope it solves your slowness problem.
-
0
In the meantime you can rebuild your DB indices or add missing indices see https://blog.sqlauthority.com/2011/01/03/sql-server-2008-missing-index-script-download/
-
0
Hi @alper my database is on the cloud and services are working on-premises so if there is too much round trip that may cause too much latency. And for 900 records 4.5 second is not also a good time. Is it possible to change fetching all records to fetching only current page records. And also could you please check if there is a loop for user or tenant info fetch?
-
0
hi enes.koroglu
I will check it and see what we can do.
-
0
Hi @maliming
Any news about this problem?
-
0
hi
This query cannot be paged, because the data is actually a linked list structure.
Can you share the full log of the
link-user
request with me? liming.ma@volosoft.com
Please lower the log level to see more detailed logs.##.MinimumLevel.Override("Microsoft", LogEventLevel.Information) ##.MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning)
-
0
Sent via mail
-
0
hi
You can do some changes by https://github.com/abpframework/abp/pull/15892 the
IdentityLinkUserAppService.cs
file I sent by mail. -
0
Please compare the performance after applying the changes. Thanks
-
0
Hi @maliming
Your code (Pull Request) works on Abp 7.2, our project is Abp 5.3.3 so we had to change some codes. I changed
IdentityUserRepository
variable's type fromIIdentityUserRepository
toIRepository<IdentityUser>
. And did a second change on using IdentityUserRepository like below://var users = await IdentityUserRepository.GetListByIdsAsync(userGroup.Select(x => x.TargetUserId)); //changed above code like below var users = (await IdentityUserRepository.GetQueryableAsync()) .Where(p => userGroup.Select(p => p.TargetUserId).Contains(p.Id)).ToList();
In this scenario operation time gets to 15 seconds from 30 seconds.
We made a performance improvement on your code like below and operation time is reduced to 10 seconds from 15 seconds with this change below (increased round trip on your code):
List<IdentityUser> allUsers = new(); //added using (dataFilter.Disable()) //added { allUsers = (await IdentityUserRepository.GetQueryableAsync()) //added .Where(p => allLinkUsers.Select(p => p.TargetUserId).Contains(p.Id)).ToList(); //added } //added foreach (var userGroup in allLinkUsers.GroupBy(x => x.TargetTenantId)) { var tenantId = userGroup.Key; TenantConfiguration tenant = null; if (tenantId.HasValue) { tenant = await TenantStore.FindAsync(tenantId.Value); } using (CurrentTenant.Change(tenantId)) { //var users = await IdentityUserRepository.GetListByIdsAsync(userGroup.Select(x => x.TargetUserId)); //commented //changed above line like below line var users = allUsers.Where(p => userGroup.Select(p => p.TargetUserId).Contains(p.Id)).ToList(); //added foreach (var user in users) { userDto.Add(new LinkUserDto { TargetUserId = user.Id, TargetUserName = user.UserName, TargetTenantId = tenant?.Id, TargetTenantName = tenant?.Name, DirectlyLinked = userGroup.FirstOrDefault(x => x.TargetUserId == user.Id)?.DirectlyLinked ?? false }); } } }
Note We reduced operation time to 10 seconds and nearly all the time is used by below code line. We inspected source of
IdentityLinkUserManager.GetListAsync()
method from github and this method makes too much round trips:var linkUsers = await IdentityLinkUserManager.GetListAsync(new IdentityLinkUserInfo(currentUserId, currentTenantId), includeIndirect: true);
-
0
We inspected source of IdentityLinkUserManager.GetListAsync() method from github and this method makes too much round trips:
includeIndirect: true will have a large number of queries, which is inevitable.