Hi sideshow,
So the search takes a customer and an organisation and finds all products that match, based on the classifications and regions the customer is assigned to, and the classifications and regions a product is for? So the search always takes the customer and organisation as input, and provides a collection of products as output?
You know this already, but 6 to 10 hours is an eternity for a query.
Is the product/organisation/classification/customer data fairly stable? I.e. it's less common to be creating these instances than it is to be performing the search?
Suggestion 1: The sledgehammer approach:
Create a class that represents a Customer/Product/Organisation combination:
Code: Select all
OrganisationCustomerProduct:
myCustomer (child) (inversed to allCustomerProducts on Customer)
myProduct (child) (inversed to allCustomerProducts on Product)
myOrganisation (child) (inversed to allCustomerProducts on Organisation)
Write a script that creates instances of this class based on the products that a customer can see. You'll need to update these objects as customers/regions/classifications etc are changed.
The upside: searching is now instant - you have the collection of products for a customer/organisation.
The downside: it'll take a long time to create those instances, there will be a LOT of them, and you'll need to manage contention when refreshing the data. I would do this with a "single writer process" mechanism such as a server background process that is the only thing allowed to update these objects, using updateLocks.
Suggestion 2: Somewhere in between suggestion 1 (full caching of results) and what you have now (no caching of results).
Create a class that represents all products for a particular organisation/classification combination, like this:
Code: Select all
OrganisationClassification:
myOrganisation (child) inversed to allOrgClassRegions on Organisation
myClassification (child) inversed to allOrgClassRegions on Classification
allProductRegions keyed by myRegion (peer-peer) inversed to allOrgClassRegions on Classification
ProductRegion:
allProducts
myRegion
myOrgansationClassification
There would be an MKD holding the OrganisationClassification objects at some global level keyed by:
myOrganisation
myClassification
JADEish pseudocode for searching is something like this:
Code: Select all
foreach classification in customer.allInterectedClassifications do
orgClassification := root.allOrganisationClassifications.getAtKey(searchedForOrganisation, classification);
if (orgClassification = null) then continue;
iter := orgClassification.allProductRegions.createIterator();
foreach region in customer.allInterestedRegions do
productRegion := orgClassification.allProductRegions.getAtKey(region);
if (productRegion = null) then continue;
iter.startAtObject(productRegion);
while (iter.next(productRegion) and (productRegion.myRegion = region)) do
//copy the products on this ProductRegion instance to our results
//may need to filter out duplicates.
productRegion.allProducts.copy(queryResult);
endwhile;
endforeach;
endforeach;
This approach is still caching results, but at a lower lever, so the time to build these cached structures will be lower and the database bloat will be less than the first solution. Searching speed will be slightly slower than the first solution but should be no where near as slow as what you're seeing now. To relieve contention during updates have a single writer thread responsible for updating these structures.
Anyway, I hope this helps you find a way forward.