Skip to main content

QMC performance – best practices

ON THIS PAGE

QMC performance – best practices

To maintain optimal performance in the Qlik Management Console (QMC), it is important that you know about some of the key factors affecting QMC performance. By following the advice in this topic, you reduce the risk of experiencing slow response times and other issues originating from inappropriate use of the QMC.

Suggestions for improved performance

When planning, setting up, and maintaining the QMC, consider the following options for improved performance. Some of them involve minor sacrifices that may be worthwhile.

  • Number of admins: The QMC is not designed to be a self-service tool, it is intended for a limited number of administrators. Keeping the number of admins down benefits performance.
  • Number and size of apps: Housekeeping is recommended. Check for unused or rarely used apps and remove them, if possible. Very large apps might be split into smaller ones.
  • Design of the security rules: Properly designed security rules can improve performance, see Security rules.
  • Security rules caching, see Security rules caching.
  • Counters: Queries for showing numbers in the QMC can be removed to improve performance.
  • Central logging: Turn off central logging to reduce load on the database. This comes at the cost of minor monitoring app functionality.
  • Custom filters: Use custom filters to quickly access the data you want to work with. Data connected to custom filters is cached in the browser. When you switch between custom filtered views, only changes to the data are loaded. This is faster than a full table reload. See Managing custom filters in table views.

Security rules

Security rules grant users access to resources where they can perform certain actions, such as create, read, update, and delete, given that certain conditions are fulfilled.

Security rules are always inclusive, that is, they are always used to grant a user access. A security rule never actively excludes a user, but if a user is not included in any security rule granting access, the user is, in effect, denied access. The main point, though, is that it is sufficient that there is one rule for granting a user access to a resource for the user to be able to access the resource. That many rules, indirectly, exclude the user is irrelevant.

When a security rule grants access to a resource rule evaluation stops. The worst-case scenario for rule evaluation is when a user has no privileges at all, in which case all security rules are evaluated.

Security rules caching

The Qlik Sense security rule mechanism includes two different cache layers that have been implemented to increase rule evaluation performance:

  • Security rule cache (rule engine)
  • Security filter result cache (Qlik Sense Repository Service)

Security rule cache

The rule engine is a component used for parsing rules to evaluate access to resources. The security rule cache exists in the rule engine and consists of parsed system rules. The cache is not stored in the database and is deleted when Qlik Sense Repository Service is restarted. If there are no changes to the security rules, the cache will not be reset, which benefits performance.

When the rule engine filters out what rules to use, depending on the resource filter, context, and actions, the rules are sorted with the ones granting access most frequently first.

Security filter result cache

This cache exists in Qlik Sense Repository Service. Using this cache avoids using the rule engine. The cache is not stored in the database and is deleted when Qlik Sense Repository Service is restarted. There are three cache categories that are invalidated (deleted) in different ways:

• Global cache: Any change to security rules, load balancing rules, license rules, or custom properties, will trigger complete invalidation of the cache. As a consequence, any optimizations gained since the session started are lost.

• User cache: Changes to user attributes or custom properties will trigger user-based invalidation, that is, the cache related to that specific user is deleted.

• Entity cache: Any change to a single entity (for example, changing app name or owner) will trigger entity-based invalidation, that is, the cache related to that specific entity is deleted.

Related logs

The following logs are related to cache invalidation of security filter results. You can use them for troubleshooting and monitoring purposes. The logs are found here: C:\ProgramData\Qlik\Sense\Log\Repository\Trace\HOST_NAME_Audit_Repository.txt.

Invalidating entire security filter result cache due to {reason} (Logged at Info level)

Invalidating security filter result cache for user with id: {userId} (Logged at Debug level)

Invalidating security filter result cache for entity (type_id): {entity.Type.Name}_{entity.Id} (Logged at Debug level)

Guidelines for writing performance efficient security rules

The following guidelines represent general best practices when writing security rules. In addition to these common guidelines, your specific environment may have more potential improvements that are not presented here.

Use specific resource filter

Before access to a resource is evaluated, the rules that apply to that resource are filtered out with the resource filter. Therefore, it is important that the resource filter is as specific as possible. The more specific the filter, the fewer the rules that must be processed by the rule engine.

The following table shows an example of resource filters of different efficiency.

Resource filters
Resource filter Evaluation target Efficiency

*

All resources Least  efficient
app* All resources that start with “app” (for example, app, app.object) More  efficient than the above
app_* App resources More  efficient than the above
app_644d2485-d318-45b0-996e-29f5d379cac2 App resource with id 644d2485-d318-45b0-996e-29f5d379cac2 Most efficient

Even if the last example is the most efficient, it also has very limited reusability. The general recommendation is to specify resource type to a level where any test on resource type in the rule is unnecessary.

Use correct context and target specific actions

Before access to a resource is evaluated, rules that apply to that resource are filtered with the correct context and actions.

Only in hub, Only in QMC, or Both in hub and QMC are the three context alternatives. Again, be as specific as possible. The first two are more efficient because only one case is evaluated. Furthermore, you should specify the actions that the rule should allow rather than using full CRUD access (create, read, update, delete).

Avoid traversing several object reference boundaries

In many cases it improves efficiency to be as specific as possible, but not always. The following two examples show rules that are designed to give a user read access to a reload task.

Example 1:  

user@property=resource.app.stream@property

Outcome: The user can read a reload task if the user has a custom property that matches a custom property on the stream of the app of the task.

Inefficient, object reference boundaries (app and stream) are traversed, which is expensive.

Example 2:  

user.@property=resource.@property

Outcome: The user can read a task if the user has a custom property that matches a custom property directly on the task.

More efficient, avoids traversing boundaries.

Minimize the number of custom properties

Less is sometimes more efficient. Keeping the number of custom properties to a minimum is advantageous.

Example 3:  

user.@CustomProperty=resource.@CustomProp2

Not recommended because two custom properties must be fetched from the repository.

Example 4:  

user.@customProperty=“ReaderOnly”

Recommended because only one custom property must be fetched from the repository.

Order of execution in rule syntax matters

When writing rules, you should have the more expensive operation last. In the following examples, it is enough that one of the conditions is true. If the less expensive operation comes first and is true, the more expensive operation never needs to be evaluated.

Example 5:  

resource.app.stream.owner.@a = “b” or user.name = “user1”

Less efficient because the more expensive operation is evaluated first.

Example 6:  

user.name = “user1” or resource.app.stream.owner.@a = “b”

More efficient, the more expensive operation comes last, and will only be evaluated if the first operation is false.

Avoid hard coded values – use attributes instead

It is preferable to use a rule like resource.@property == user.name, instead of several rules with hard coded strings resource.@property  == "user1"  ,  resource.@property == "user2".

HasPrivilege is less efficient

If possible, avoid HasPrivilege("action") as it triggers a second rule evaluation.

Example 7:  

App.Stream.HasPrivilege("read")

The function creates a new instance of the rule engine that triggers a second evaluation of the rules.