The Business Logic Engine is architected to Minimize/Eliminate SQL overhead.
the Business Logic Engine analyzes updates, and avoids parent access, adjustment and cascade when the referenced data is not changed
Unlike Rete Business Rule Engines
that load all the data into memory, or issue aggregate
queries, this assures optimal performance. This is particularly
important with there are chained aggregates
System Performance Optimizations to avoid/minimize SQL
Role Pruning avoids database operations along a role if the
referenced data is not altered. Significant cases are noted in the
sub-sections below. Also, see Performance for Best Practices.
Pruning detects that when certain database changes to do affect other rules, these rules - and their associated SQL overhead - can be safely skipped.
Formula Pruning if no local Domain Object changes
As explained in Formula Execution, Formulas can contain parent references, such as:
A = B + C + Parent.Attribute
Parent References requires (possibly cached) SQL to obtain the parent data. These are expensive, so are pruned if possible.
The Business Logic Engine will detect that this SQL is not required if
- B and C (referenced local attributes) are not altered
- The system can determine that Parent.Attribute has not been altered
Adjustment Pruning if no child summed/qual/fk change
Parent Adjustment is bypassed in the attributes referenced in Child objects are not changed.
Cascade Pruning if no Parent Reference changes
Forward Chain Cascade altered Parent References to Children is bypassed if the Parent References (Parent Attributes referenced by Child rules) are not changed.
In our example above, changes to Parent are analyzed; if Parent.Attribute' is not changed, there is no cascade to the referencing children.
Adjustment (vs. Aggregate Queries)
For Non-transient aggregates (recommended Best Practice), the system utilizes adjustment logic (instead of aggregate
Select sum queries - see Execute Adjustment (or Recompute)).
Forward chaining is the core of solving complex problems with simple
expressions. This very quickly leads to aggregates that operate on
other aggregated results.
For example, in BusLogicDemo,
Customer.balance = sum (orders.total)
which depends on another aggregate:
Purchaseorder.total = sum(lineitem.amount)
Without adjustment, the system would need to materialize each
Purchaseorder.total - n aggregate queries (where there are n orders for a customer).
The implications are even more extreme when there is recursive
nesting. Changing a Department Budget would literally require reading
all the departments. Adjustment logic is key to enterprise transaction
A common database design Best Practice is to avoid redundant data by
normalizing the data model. Persistent aggregates are redundant, since
their value is derived from other data.
We still recommend persistent aggregates:
- The often-extreme performance considerations
- Guaranteed Integrity
- The guiding motivation behind avoiding redundancy is data
inconsistency: what if a program failure results in a different stored
vs. computed aggregate. A problem, indeed. But Business Logic
eliminates the programming entirely, so there is no risk of data
- We regard a persistent aggregate as analogous to relational index: a performance option that has no effect on your code
Performance Best Practices
We recommend that sum/count attributes be defined as persistent (not transient) attributes, since this enables adjustment processing defined above. Transient support is provided to support requirements where the database schema cannot be altered (e.g., is being used by other software), and for situations with a very small number of related child data.
Transient parent references
We recommend that parent referenced attributes be accessed by dot notation (see, for example, the derivation for
qtyOrdered in the Bill of Materials Rollup example).