Optimize sample and list operations, including auditing and user lookups - #8020
Optimize sample and list operations, including auditing and user lookups#8020labkey-jeckels wants to merge 13 commits into
Conversation
- Audit inserts no longer rebuild the audit table's metadata on every event - Provider-generated audit events raised during a bulk operation are batched instead of inserted one at a time - List inserts, updates, and deletes write their audit rows per operation rather than per row, and stop re-resolving column names for every row - Sample timeline audit writes are chunked so a large sample operation doesn't hold every event in memory - Fixes lookup value resolution being re-queried on every row during import, where it should have been memoized
- Audit inserts no longer rebuild the audit table's metadata on every event - Provider-generated audit events raised during a bulk operation are batched instead of inserted one at a time - List inserts, updates, and deletes write their audit rows per operation rather than per row, and stop re-resolving column names for every row - Sample timeline audit writes are chunked so a large sample operation doesn't hold every event in memory - Fixes lookup value resolution being re-queried on every row during import, where it should have been memoized
The cached provisioned TableInfo pins its Domain's DomainDescriptor, which MemTracker tracks separately, so the leak check never reached zero. StorageProvisioner.createSharedTableInfo() now owns the locking and untracking for both.
# Conflicts: # api/src/org/labkey/api/data/MaterializedQueryHelper.java
| ContainerFilter cf = null == containerFilter ? ContainerFilter.current(container, user) : containerFilter; | ||
| Collection<GUID> ids = scopeIds(user, container, cf); | ||
| if (null == ids) | ||
| return event -> true; |
There was a problem hiding this comment.
nit: Rename event to _.
| if (null == ids) | ||
| return event -> true; | ||
|
|
||
| Set<GUID> scope = new HashSet<>(ids); |
There was a problem hiding this comment.
Just curious, why copy the collection here? To ensure it is a set?
There was a problem hiding this comment.
It's more important to have a hashed collection than to ensure no dupes. Realistically, this won't be huge in practice, but better to guarantee an O(1) lookup. We should probably swap from Collection to Set in ContainerFilter but that's way out of scope.
|
|
||
| private static String indexKey(List<String> columnNames) | ||
| { | ||
| return columnNames.stream().map(name -> name.toLowerCase(Locale.ROOT)).collect(Collectors.joining(",")); |
There was a problem hiding this comment.
Should this sort the columns so that the key is consistent/reproducible?
There was a problem hiding this comment.
I don't think so. An index over (x,y) is not the same as one over (y,x). The UI doesn't let you define custom multi-column indices today but the API does.
Rationale
Speed up sample and list operations by taking per-row work out of the audit write path, the list audit formatter, and import lookup resolution. Create custom sample type indices in the materialized tables so that grids over large sample types stop scanning.
Related Pull Requests
Changes
Tasks