Base solution for your next web application
Open Closed

Numerous queries #8291


User avatar
0
tinytownsoftware created

Hello, I was looking at my Azure SQL usage and this query popped up as very frequent. In the past 24 hours it has been executed 21295 times. Any ideas where it's coming from and why it's so frequent?

(@__ef_filter__p_3 bit,@__ef_filter__p_4 bit,@__ef_filter__CurrentTenantId_5 int,@__ef_filter__p_6 bit,@__ef_filter__p_7 bit,@__ef_filter__CurrentTenantId_8 int,@__ef_filter__p_0 bit,@__ef_filter__p_1 bit,@__ef_filter__CurrentTenantId_2 int,@__user_Id_0 bigint)SELECT [t0].[Name] FROM [AbpUserOrganizationUnits] AS [a] INNER JOIN ( SELECT [a0].[Id], [a0].[CreationTime], [a0].[CreatorUserId], [a0].[IsDeleted], [a0].[OrganizationUnitId], [a0].[RoleId], [a0].[TenantId] FROM [AbpOrganizationUnitRoles] AS [a0] WHERE ((@__ef_filter__p_3 = CAST(1 AS bit)) OR ([a0].[IsDeleted] <> CAST(1 AS bit))) AND ((@__ef_filter__p_4 = CAST(1 AS bit)) OR ((([a0].[TenantId] = @__ef_filter__CurrentTenantId_5) AND ([a0].[TenantId] IS NOT NULL AND @__ef_filter__CurrentTenantId_5 IS NOT NULL)) OR ([a0].[TenantId] IS NULL AND @__ef_filter__CurrentTenantId_5 IS NULL))) ) AS [t] ON [a].[OrganizationUnitId] = [t].[OrganizationUnitId] INNER JOIN ( SELECT [a1].[Id], [a1].[ConcurrencyStamp], [a1].[CreationTime], [a1].[CreatorUserId], [a1].[DeleterUserId], [a1].[DeletionTime], [a1].[DisplayName], [a1].[IsDefault], [a1].[IsDeleted], [a1].[IsStatic], [a1].[LastModificationTime], [a1].[LastModifierUserId], [a1].[Name], [a1].[NormalizedName], [a1].[TenantId] FROM [AbpRoles] AS [a1] WHERE ((@__ef_filter__p_6 = CAST(1 AS bit)) OR ([a1].[IsDeleted] <> CAST(1 AS bit))) AND ((@__ef_filter__p_7 = CAST(1 AS bit)) OR ((([a1].[TenantId] = @__ef_filter__CurrentTenantId_8) AND ([a1].[TenantId] IS NOT NULL AND @__ef_filter__CurrentTenantId_8 IS NOT NULL)) OR ([a1].[TenantId] IS NULL AND @__ef_filter__CurrentTenantId_8 IS NULL))) ) AS [t0] ON [t].[RoleId] = [t0].[Id] WHERE (((@__ef_filter__p_0 = CAST(1 AS bit)) OR ([a].[IsDeleted] <> CAST(1 AS bit))) AND ((@__ef_filter__p_1 = CAST(1 AS bit)) OR ((([a].[TenantId] = @__ef_filter__CurrentTenantId_2) AND ([a].[TenantId] IS NOT NULL AND @__ef_filter__CurrentTenantId_2 IS NOT NULL)) OR ([a].[TenantId] IS NULL AND @__ef_filter__CurrentTenantId_2 IS NULL)))) AND (([a].[UserId] = @__user_Id_0) AND @__user_Id_0 IS NOT NULL)


15 Answer(s)
  • User Avatar
    0
    aaron created
    Support Team

    It appears to be from GetAllRoleNamesOfUsersOrganizationUnits, which is called in GetUserForEdit.

  • User Avatar
    0
    tinytownsoftware created

    Intersting. I don't see how that is possible. That is a manual/interactive administrator action, so I don't see how it's being executed 14 times per minute. Could there be another place? It looks like it's happening on page loads.

  • User Avatar
    0
    aaron created
    Support Team

    Oh, there is an identical query in ASP<span></span>.NET Boilerplate's GetRoles, which is called in GetUserPermissionCacheItem to populate the cache for IsGranted.

  • User Avatar
    0
    tinytownsoftware created

    I see. I have very simple permissioning that doesn't change. Is there any way to increase this cache's ttl so as to minimize these queries?

  • User Avatar
    0
    aaron created
    Support Team

    Yes, you can configure the cache's DefaultSlidingExpirationTime.

    https://aspnetboilerplate.com/Pages/Documents/Caching#configuration

  • User Avatar
    0
    tinytownsoftware created

    Thank you very much!

  • User Avatar
    0
    tinytownsoftware created

    Reopening. This did not actually fix the issue with numerous queries. I can't tell if it's Abp making them or Zero. Below is a screenshot with Azure with the most numerous queries (sorted descending). The one on the bottom is a query from my application. I don't have multi-tenantcy enabled, my permissions are very straightforward, I have two roles, one user and one admin and that's about it. The amount of database requests is much too high. What can I do about this?

    The tables being queries are: AbpUsers AbpRoles The original query above is #3 in the list A join on AbpUserRoles and AbpRoles AbpRoleClaims AbpUserClaims

  • User Avatar
    0
    aaron created
    Support Team

    How many users do you have? The application needs to make 2 DB calls (join queries) per active user.

    You can override AbpUserStore.GetRoles to aggressively cache each Role and OrganizationUnitRole in memory. This would not reduce the number of queries, since the application still needs to query UserRole and UserOrganizationUnit (assuming you have a sizeable number of users), but at least it would be single-table queries.

    Do you use UserOrganizationUnit? If you don't, then aggressively caching just Role is sufficient — reducing 2 join queries to 1 simple query.

  • User Avatar
    0
    tinytownsoftware created

    I have about 800 users right now. Which is why the execution counts look very high to me, because it's not a lot of users.

    I don't use UserOrganizationUnit. I will try the caching you mentioned, thanks!

  • User Avatar
    0
    tinytownsoftware created

    Wow, there are so many calls to UserStore.FindByIdAsync and UserStore.GetRolesAsync in a single page load. Time to do some caching!

  • User Avatar
    0
    tinytownsoftware created

    Where does the application query UserRole and UserOrganizationUnit? Why can't I cache those too?

  • User Avatar
    0
    aaron created
    Support Team

    In the join queries mentioned earlier.

    You can cache those too; the effect is probably less than the caching of non-user-specific Role.

  • User Avatar
    0
    tinytownsoftware created

    Understood.

    One more thing: Caching of User result in UserStore.FindByIdAsync will have a high impact, because that is #1 by count. It's easy enough to cache it there, but I am afraid that it will have unforeseen consequences if I forget to update the cache when a given user is updated. Besides AccountController and AccountAppService, is there any other place where I should invalidate the userid from the cache?

  • User Avatar
    0
    aaron created
    Support Team

    I recommend that you invalidate via Domain Event handlers, rather than in certain API. You can take ASP<span></span>.NET Boilerplate's AbpUserPermissionCacheItemInvalidator as a reference.

    Domain Events: https://aspnetboilerplate.com/Pages/Documents/EventBus-Domain-Events

  • User Avatar
    0
    tinytownsoftware created

    I didn't know about that, thanks! Closing again.