Skip to content

Database Performance

This document describes the behaviour of Security servers (SecurityAPI, Authorization) related to database interactions and SQL statements executed.

Database

Security servers interact with these SQL databases:

  • Authentication: Logging DB.
  • Authorization: Logging DB.
  • SecurityAPI: Multi-tenant DB, Tenant DB, Logging DB.

As we see, only SecurityAPI interacts with business databases through two data context: authentication context and authorization context. Logging databases could be different for each server but in this document all servers share the same logging DB.

SQL statements sequence for Authorization server endpoints

Authorization server has two GET endpoints HasPermissions y EffectivePermissions with same logging flow. We've considered only happy path scenario. There are two possible execution paths for each request depending on if request is cached or not:

1. Cache contains response

Authorization cache OK

  • Debug: 1 insert bulk per request. Each 5 seconds several insert bulk operations depending on the number of cache interactions.
  • Information: 0 insert bulk per request.

2. Cache not contains response

Authorization cache KO

  • Debug: 1 insert bulk per request and 4 queries required for database context creation and 1 to n executions of get_user_effective_permissions store procedure depending on number of groupKeys supplied as requests' parameter. Each 5 seconds several insert bulk operations depending on the number of cache interactions.
  • Information: 0 insert bulk per request and 4 queries required for database context creation and 1 to n executions of get_user_effective_permissions store procedure depending on number of groupKeys supplied as requests' parameter.

Load Tests Setup

We used the same configuration for testing the Authorization server endpoints:

  • 30 minutes running.
  • Step goal of 100 users.
  • Initial users are 10, adding 5 users each 10 seconds.
  • Using Kangaroo environment.
  • Data used: 2 applications, 5 groups, 5 users, 13 securables.

Results (Debug)

HasPermissions (Debug)

Results
Max User Load 100
Tests/Sec 556
Tests Failed 0
Avg. Test Time (sec) 0.15
Transactions/Sec 0
Avg. Transaction Time (sec) 0
Pages/Sec 556
Avg. Page Time (sec) 0.15
Requests/Sec 556
Requests Failed 0
Requests Cached Percentage 0
Avg. Response Time (sec) 0.15
Avg. Content Length (bytes) 4.69
Total Tests 1,001,409
Failed Tests (% of total) 0 (0%)

Great performance in Request/sec (556), Avg. Response Time(0.15), Total Tests (≈1M) and Failed Test (0).

Page response time graph

Cache usage
Requests not in cache 808 0.08%
Requests in cache 1,000,601 99.92%
Total request 1,001,409 100%

High cache usage reduces in a great way the execution of sql statements.

| SQL Statement | Times | Total Execution Time(s) | Average Execution Time (s) | |---------------------------------------------------------------------------------------------------------------------------| | insert bulk... | 1,050,472 | 11,556.447392 | 0.011001 | | SELECT COUNT(*)... | 1,616 | 0.053103 | 0.000033 | | SELECT TOP(2)... | 1,616 | 0.053103 | 0.000033 | | exec [Authorization].get_user_effective_permissions... | 96 | 0.033657 | 0.000351 | | exec [Authorization].get_user_effective_permissions... | 96 | 0.038144 | 0.000397 | | exec [Authorization].get_user_effective_permissions... | 96 | 0.027399 | 0.000260 | | exec [Authorization].get_user_effective_permissions... | 96 | 0.024993 | 0.000260 | | exec [Authorization].get_user_effective_permissions... | 96 | 0.029346 | 0.000306 | | exec [Authorization].get_user_effective_permissions... | 49 | 0.017426 | 0.000355 | | exec [Authorization].get_user_effective_permissions... | 49 | 0.013298 | 0.000271 |

SELECT operations are unnecessary repeated but them are executed fast (0.033 ms). Executions of SP are fast too, between 0.25 ms and 0.4ms. Insert bulk operations are clearly slowest with 11ms.

Top slowest statements Execution Time(s)
insert bulk 4.746
insert bulk 3.925
insert bulk 2.989
insert bulk 2.792
insert bulk 1.996

This slowest statements could correspond to cache logger writings when concurrent users are 100. At this point there are 556+ (CacheActionLogs/request*Request/sec*5s)=(35565)/50≈167 concurrent insert bulk.

EffectivePermissions (Debug)

Results
Max User Load 100
Tests/Sec 3.31
Tests Failed 0
Avg. Test Time (sec) 18.4
Transactions/Sec 0
Avg. Transaction Time (sec) 0
Pages/Sec 3.31
Avg. Page Time (sec) 18.4
Requests/Sec 2.88
Requests Failed 0
Requests Cached Percentage 0
Avg. Response Time (sec) 18.4
Avg. Content Length (bytes) 370
Total Tests 5,958
Failed Tests (% of total) 0 (0)

Low performance in Request/sec (2.88), Avg. Response Time(22.8s), Total Tests (≈5K). Page response time graph

Cache usage
Requests not in cache 39 0.65%
Requests in cache 5,919 99.35%
Total request 5,958 100%

High cache usage reduces in a great way the execution of sql statements.

| SQL Statement | Times | Total Execution Time(s) | Average Execution Time (s) | |---------------------------------------------------------------------------------------------------------------------------| | insert bulk... | 7,759 | 46.311679 | 0.005969 | | SELECT COUNT(*)... | 74 | 0.002629 | 0.000035 | | SELECT TOP(2)... | 74 | 0.002629 | 0.000035 | | exec [Authorization].get_user_effective_permissions... | 3 | 0.009615 | 0.003205 | | exec [Authorization].get_user_effective_permissions... | 3 | 0.000750 | 0.000250 | | exec [Authorization].get_user_effective_permissions... | 2 | 0.000731 | 0.000366 | | exec [Authorization].get_user_effective_permissions... | 2 | 0.028336 | 0.014168 | | exec [Authorization].get_user_effective_permissions... | 2 | 0.000455 | 0.000226 | | exec [Authorization].get_user_effective_permissions... | 2 | 0.000448 | 0.000224 | | exec [Authorization].get_user_effective_permissions... | 2 | 0.000627 | 0.000314 |

SELECT operations are unnecessary repeated but them are executed fast (0.033 ms). Executions of SP are fast mainly, between 0.25 ms and 0.36ms but are two operations quite slow, between 1.4ms and 3.2ms. Insert bulk operations are clearly slowest with 5.9ms.

Top slowest statements Execution Time(s)
insert bulk 16.996
insert bulk 10.011
insert bulk 0.499
insert bulk 0.073

Inexplicable results for the first two statements.

Commentaries

This results for EffectivePermissions are inexplicable because the execution path is pretty much similar to HasPermissions endpoint and it should be a slightly minor due to serialization of the response and response size. Many load test with empty logging database, different LoadTest database has been tried with no results.

Results (Information)

HasPermissions (Information)

Results
Max User Load 100
Tests/Sec 448
Tests Failed 0
Avg. Test Time (sec) 0.17
Transactions/Sec 0
Avg. Transaction Time (sec) 0
Pages/Sec 468
Avg. Page Time (sec) 0.16
Requests/Sec 448
Requests Failed 0
Requests Cached Percentage 0
Avg. Response Time (sec) 0.15
Avg. Content Length (bytes) 4.71
Total Tests 843,249
Failed Tests (% of total) 0 (0%)

Great performance in Request/sec (448), Avg. Response Time(0.16s), Total Tests (≈850K) and Failed Test (0).

Page response time graph

Cache usage
Requests not in cache ≈1606 0.19%
Requests in cache 841,643 99.81%
Total request 843,249 100%

Cache has no impact on logging.

Generated logging traces
Action logs 0 0%
Cache Action logs 0 0%
Total logs 0 0%

No Information logging traces.

| SQL Statement | Times | Total Execution Time(s) | Average Execution Time (s) | |---------------------------------------------------------------------------------------------------------------------------| | SELECT COUNT(*)... | 1,606 | 0.041983 | 0.002614 | | SELECT TOP(2)... | 1,606 | 0.044243 | 0.002755 | | exec [Authorization].get_user_effective_permissions... | 97 | 0.0.0237 | 0.000244 | | exec [Authorization].get_user_effective_permissions... | 96 | 0.022077 | 0.000230 | | exec [Authorization].get_user_effective_permissions... | 96 | 0.029830 | 0.000352 | | exec [Authorization].get_user_effective_permissions... | 96 | 0.031195 | 0.000325 | | exec [Authorization].get_user_effective_permissions... | 96 | 0.022982 | 0.002394 | | exec [Authorization].get_user_effective_permissions... | 48 | 0.011293 | 0.000235 | | exec [Authorization].get_user_effective_permissions... | 48 | 0.014901 | 0.000310 | | exec [Authorization].get_user_effective_permissions... | 48 | 0.011135 | 0.000232 |

SELECT operations are unnecessary repeated but them are executed fast (≈0.033 ms). Executions of SP are fast, between 0.20 ms and 0.38ms. No insert bulk operations due to cache configuration.

Top slowest statements Execution Time(s)
exec [Authorization].get_user_effective_permissions... 0.000740
exec [Authorization].get_user_effective_permissions... 0.000515
exec [Authorization].get_user_effective_permissions... 0.000504
exec [Authorization].get_user_effective_permissions... 0.000497
exec [Authorization].get_user_effective_permissions... 0.000479

Good. Slower statement are executed between 0.48ms and 0.74ms.

EffectivePermissions (Information)

Results
Max User Load 100
Tests/Sec 9.53
Tests Failed 0
Avg. Test Time (sec) 0.012
Transactions/Sec 0
Avg. Transaction Time (sec) 0
Pages/Sec 9.53
Avg. Page Time (sec) 0.01
Requests/Sec 9.53
Requests Failed 0
Requests Cached Percentage 0
Avg. Response Time (sec) 0.01
Avg. Content Length (bytes) 370
Total Tests 17,154
Failed Tests (% of total) 0 (0)

Moderate performance in Request/sec (9.53) and Total Tests (≈17K). Great performance in Avg. Response Time(0.01s).

Page response time graph

Cache usage
Requests not in cache ≈72 ≈0.41%
Requests in cache 17,082 99.58%
Total request 17,154 100%

High cache usage reduces in a great way the execution of sql statements.

| SQL Statement | Times | Total Execution Time(s) | Average Execution Time (s) | |---------------------------------------------------------------------------------------------------------------------------| | SELECT COUNT(*)... | 72 | 0.002507 | 0.000035 | | SELECT TOP(2)... | 72 | 0.002192 | 0.000030 | | exec [Authorization].get_user_effective_permissions... | 3 | 0.000623 | 0.000208 | | exec [Authorization].get_user_effective_permissions... | 3 | 0.000588 | 0.000294 | | exec [Authorization].get_user_effective_permissions... | 2 | 0.000704 | 0.000352 | | exec [Authorization].get_user_effective_permissions... | 2 | 0.000621 | 0.000311 | | exec [Authorization].get_user_effective_permissions... | 2 | 0.000680 | 0.000340 | | exec [Authorization].get_user_effective_permissions... | 2 | 0.000404 | 0.000202 | | exec [Authorization].get_user_effective_permissions... | 2 | 0.000749 | 0.000375 | | exec [Authorization].get_user_effective_permissions... | 2 | 0.000692 | 0.000346 |

SELECT operations are unnecessary repeated but them are executed fast (≈0.033 ms). Executions of SP are fast, between 0.20 ms and 0.38ms. No insert bulk operations due to cache configuration.

Top slowest statements Execution Time(s)
exec [Authorization].get_user_effective_permissions... 0.000421
exec [Authorization].get_user_effective_permissions... 0.000414
exec [Authorization].get_user_effective_permissions... 0.000404
exec [Authorization].get_user_effective_permissions... 0.000346
exec [Authorization].get_user_effective_permissions... 0.000344

Great. Slower statement are executed is less that 0.42ms

Commentaries

This results for EffectivePermissions are inexplicable because the execution path is pretty much similar to HasPermissions endpoint and it should be a slightly minor due to serialization of the response and response size. Many load test with empty logging database, different LoadTest database has been tried with no results.

Improvements

  • Cache Multi-tenant DB operations could save unnecessary calls to this DB but saved time will be just a little.
  • get_user_effective_permissions SP could be optimized and this way avoid some long execution peaks.