FIX 11577 performance issues with large list of groups#11578
FIX 11577 performance issues with large list of groups#11578beerbohmdo wants to merge 1 commit intosilverstripe:5from
Conversation
120baae to
c8b41b0
Compare
GuySartorelli
left a comment
There was a problem hiding this comment.
Thanks for submitting this - I've requested a few changes below.
FYI the beta release for CMS 5.4 (which is also the feature freeze for all of CMS 5) is currently scheduled for Feb 17, so for this change to be included in CMS 5 it will need to be merged before then.
I will do my best to be quick to respond and review this PR as you update it.
src/Security/Group.php
Outdated
| private static $searchable_fields = [ | ||
| 'Title', | ||
| 'Description', | ||
| ]; |
There was a problem hiding this comment.
I don't think this change should alter the searchable fields
There was a problem hiding this comment.
Without the default search context is empty and the SearchableDropdownField does not filter.
src/Security/Group.php
Outdated
| $threshold = DBForeignKey::config()->get('dropdown_field_threshold'); | ||
| $overThreshold = $groups->count() > $threshold; |
There was a problem hiding this comment.
We shouldn't be using that unrelated configuration here.
There was a problem hiding this comment.
This are the default settings for SearchableDropdownField. I can create a extra config for that.
| public function getBreadcrumbTitle(): string | ||
| { | ||
| return $this->getBreadcrumbs(' > '); | ||
| } |
There was a problem hiding this comment.
Why do we need this new method?
There was a problem hiding this comment.
This is the Label for the FormField.
| private function dedupeCode(): void | ||
| { | ||
| $currentGroups = Group::get() | ||
| ->exclude('ID', $this->ID) | ||
| ->map('Code', 'Title') | ||
| ->toArray(); | ||
| $code = $this->Code; | ||
| $count = 2; | ||
| while (isset($currentGroups[$code])) { | ||
| $code = $this->Code . '-' . $count; | ||
| $count++; | ||
|
|
||
| if ($code) { | ||
| while ($this->checkIfCodeExists($code)) { | ||
| $code = $this->Code . '-' . $count; | ||
| $count++; | ||
| } | ||
|
|
||
| $this->setField('Code', $code); | ||
| } | ||
| $this->setField('Code', $code); | ||
| } | ||
|
|
||
| private function checkIfCodeExists(string $code): bool | ||
| { | ||
| return Group::get()->filter('Code', $code)->exclude('ID', $this->ID)->exists(); | ||
| } |
There was a problem hiding this comment.
How do changes to the deduping code relate to usage of a different form field?
There was a problem hiding this comment.
This is more or less the same issue as with the large list in the FormField. Without you are not able to save a group if you have many of them.
There was a problem hiding this comment.
You can check the output of my generater script above with and without the change. Without the script will get slower with each iteration.
src/Security/Member.php
Outdated
| $threshold = DBForeignKey::config()->get('dropdown_field_threshold'); | ||
| $overThreshold = $groups->count() > $threshold; |
There was a problem hiding this comment.
Like with the change in Group, we shouldn't use this unrelated configuration.
7ffbd21 to
99aaf6b
Compare
99aaf6b to
9ec4dd6
Compare
|
I created custom configs, a getter for a custom search context and added some comments. |
|
Hi @beerbohmdo, Sorry, I haven't had a chance to look at this recently and it's likely I won't get to in time for the 5.4.0 beta, which was originally scheduled to release on Monday but has been delayed slightly. This will likely need to target |
|
hi @beerbohmdo and @GuySartorelli I'm seeing the PR is a bit related to an issue I have here In my opinion, making count queries on large tables to check if over threshold is really counter productive, because making count queries on large tables is slow. I also see that this PR adds a setting very similar to what is in place in DBForeignKey (and if anything, I don't think having multiple dropdown_field_threshold settings is a good thing) Instead, I would really suggest adding a "is_large_table" on the DataObject that could be checked by any functionality that needs to determine if it needs to enable lazy loading or not This could unify fixes for:
|
I used the config from DBForeignKey before, but @GuySartorelli marked this as unrelated. If we can handle this more generic I am happy. I have many large tables in my database. |
Description
If you have many groups you can no longer edit a member in the admin.
Manual testing steps
As this is a performance issue, I am not sure howto create a unittest for this. But here is a task to create a massive amount of groups:
Issues
Pull request checklist