Skip to content

Performance issue due to DBForeignKey dropdown_field_threshold config #11645

@lekoala

Description

@lekoala

Module version(s) affected

5

Description

The DBForeignKey scaffolder makes a count() query against the table to see if it needs to enable lazy loading. But this is counter productive, because making count queries against big tables is slow.

So it's easy to get into these kind of situations

Image

The current design has multiple issues:

  • this is done during scaffolding, you cannot simply replace the field to avoid the query (instead, it could be set to "auto" and decide, upon rendering, which setting to apply)
  • counting doesn't cache anything, so if you have multiple relations against the same table, you are going to get duplicated queries
  • counting large tables is slow (even with FEAT optimize DataQuery::count for speed #11642)
  • setting the dropdown_field_threshold to 0 is still going to make a count query, even if it's going to be always true (except for empty tables)

In my opinion, instead of setting a threshold, it would be better to be able to qualify which DataObject have "large tables" (yes/no) and use that setting instead.

How to reproduce

In ModelAdmin
Have a DataObject with multiples has one relations to a large table
See that multiple count queries are issued due to scaffolding
Removing the scaffolded fields doesn't help

Possible Solution

  • Instead of counting during scaffolding, have a default "auto" mode that decides, upon php rendering, if lazy loading needs to be applied (if counting is still the preferred way)
  • Replace counting with a boolean setting per DataObject, eg: is_large_table. This could be useful in other scenarios (Remove row counting logic from GridField #11641 could benefit from this as well)
  • Always set to lazy if threshold is 0 => this seems like an easy gain :-)

Additional Context

No response

Validations

  • Check that there isn't already an issue that reports the same bug
  • Double check that your reproduction steps work in a fresh installation of silverstripe/installer (with any code examples you've provided)

PRs

Metadata

Metadata

Assignees

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions