-
Notifications
You must be signed in to change notification settings - Fork 824
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
NEW: Add Hierarchy::prepopulate_numchildren_cache() #8380
Conversation
Only relevant if silverstripe/silverstripe-framework#8380 is avialable, however coded defensively so it can be merged before that PR if needs be. See silverstripe/silverstripe-framework#8379
Note: although this didn't have an order-of-magnitude impact on performance locally (reducing treeview execution from 3.5s to 2.5s), it did reduce the query count from ~140 to ~40. This should have a greater impact on deployments where the database is running on a separate server. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK there's an issue with this: it conflicts with the lumberjack module because the lumberjack module overrides stageChildren. This causes the issue that Max found. I'm going to see if I can amend the prepopulation logic to use a call to stageChildren as the basis of its query. |
Hrm, so I looked into this, and I wonder if we declare the problem to be with lumberjack: silverstripe/silverstripe-lumberjack#86 |
You could for example do this instead:
|
The suspense is killing me |
@robbieaverill Our key project will need to add this to their config:
I think that's what is meant to be in Sam's comment. |
Your amendment looks good, Maxime. I think that there's one thing we want to note in the changelog:
|
This issue has been addressed.
@silverstripe/core-team can we get a sanity check on whether the change described in my most recent comment is okay for semver? |
I've done a sanity check via Github for The base module of this isn't even 4.x compatible (https://github.com/nyeholt/silverstripe-external-content), so I don't think it'll cause wider issues in practice - but looping in the maintainer @nyeholt in here as a courtesy either way. |
This helper is necessary when you want to replace a parameter with a non-literal such as a column name. This arises when you are transforming queries such as we do in the prepopulation query for Hierarchy::numChildren()
API: Hierarchy::stageChildren() customisations must be applied to the base class and not include record-specific behaviour. Adds the ability to prepopulate the cache for Hierarchy::numChildren() in a batch. Note that this optimisation means that stageChildren() is not called on each record in order to calculate numChildren(). This means that the structure of the stageChildren() query must be the same for all records and the behaviour cannot be customised only for a subclass of the base data class. For example, apply your customisations to SiteTree and not a subclass. This is an useful part of optimising the query count on tree generation. See #8379
This will avoid trying to count the children of childless object.
OK I've rebased this and added a note to the 4.3 changelog. |
Only relevant if silverstripe/silverstripe-framework#8380 is avialable, however coded defensively so it can be merged before that PR if needs be. See silverstripe/silverstripe-framework#8379
I've got the unit tests written, but there's an edge case that's being tripped that I didn't quite figure out how to resolve yet. I'll have another look at in the morning.
There's also a bit of an issue with unit testing the |
@ScopeyNZ I agree with the concerns about the DB::replace_parameter implementation, but a couple of notes:
|
This surprises me. Is the config applied to SiteTree or a subclass? |
public static function setUpBeforeClass() | ||
{ | ||
parent::setUpBeforeClass(); | ||
HideTestObject::config()->update( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you apply this to SiteTree instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather not as it ought to work with this and that's how the other Hierarchy test are using.
@maxime-rainville do you think I should merge the #8395 changes into this one? The relevant changes are already in silverstripe/silverstripe-cms#2266 |
Simplify prepopulate_numchildren_cache by adding a $IDLess param to stageChildren.
Sorry, I bulked down and didn't see all the messages flying. The problem was that some of the where statements in the loop where getting sent back as arrays and other were being sent back as I just took some liberties with I think it makes the logic a bit easier to follow and a bit cleaner and the generate SQL statement looks legit. SELECT DISTINCT "ParentID", COUNT(DISTINCT "SiteTree"."ID") AS "NumChildren" FROM "SiteTree" LEFT JOIN "SiteTree_Localised" AS "SiteTree_Localised_en_NZ" ON "SiteTree"."ID" = "SiteTree_Localised_en_NZ"."RecordID" AND "SiteTree_Localised_en_NZ"."Locale" = ? WHERE (("SiteTree"."ClassName" NOT IN (?, ?, ?, ?) OR "SiteTree"."ClassName" IS NULL)) GROUP BY ParentID However, it probably wouldn't hurt to have someone who actually knows what they're doing have another look at it. On the topic #8395, it probably would be better to fold it into this one, as rebasing it at this stage would probably be more trouble than its worth. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's in a good state now, but I ended up doing a big chunk of it, so it probably would be good for some one else to glance at it.
src/ORM/Hierarchy/Hierarchy.php
Outdated
} | ||
} | ||
} | ||
$query = $dummyObject->stageChildren(true, true)->dataQuery()->query(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can probably stop the implementation of DB::replace_parameter if we go with this, since it's a bit gross and was only added for this use-case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to add "Where ID != ParentID" as a filter here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added the Where ID != ParentID
statement to stageChildren.
src/ORM/Hierarchy/Hierarchy.php
Outdated
$query->setGroupBy([ | ||
"ParentID | ||
"]); | ||
$query->setGroupBy(['"ParentID"']); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's probably best to use Convert::symbol2sql("ParentID")
here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@maxime-rainville I've left a few comments — do you want to address those, then I'll rebase/squash and maybe we can get Ingo to do the final merge? |
This provides a more extensible way of preopulating caches for optimised tree generation. Fixes #8391
All done. |
* FIX: Use Hierarchy::prepopulate_numchildren_cache in tree-generation Only relevant if silverstripe/silverstripe-framework#8380 is avialable, however coded defensively so it can be merged before that PR if needs be. See silverstripe/silverstripe-framework#8379 * FIX: Use Hierarchy::prepopulateTreeDataCache() in CMS. Requires silverstripe/silverstripe-framework#8395 * Cache tree_class instead of assuming it will always be SiteTree.
Adds the ability to prepopulate the cache for Hierarchy::numChildren()
in a batch.
This is still a WIP as it will give bad results if augmentStageChildren
is used in a way that alters the number of records.
This is an useful part of optimising the query count on tree generation.
See #8379
Parent issue