Skip to content

eagerLoad elements performance issue #1372

@MrJamesEllis

Description

@MrJamesEllis

Module version(s) affected

5.4, 6

Description

I have observed performance issues that are caused by the use of the below code in ElementalPageExtension via the getEagerLoadedElements() method:

foreach (ElementalArea::get()->eagerLoad('Elements') as $elementalArea) {

This method is private and accessed in the extension via getElementsForSearch() and getContentFromElementsForCmsSearch() methods.

For some reason when "eagerLoad" is called as above, the query created by DataList::fetchEagerLoadHasMany() fetches ALL Element records for ALL ElementalArea records in the database.

e.g for a test DB with 3 pages and 3 elemental areas:

 WHERE ("Element_Live"."ParentID" IN (1, 2, 3))

Consider a DB with thousands of page records and that IN() then has thousands of values, and > thousands of records returned.

This doesn't make sense when a project just calls $page->getElementsForSearch(). The expected result when this happens is to query and return the elements attached to the ElementalArea relations of $page (there may be more than one ElementalArea on a page).

In worse case scenario this results in timeouts, e.g. if getElementsForSearch is called after a save/publish action.

How to reproduce

  1. Turn general query logging on, set a general_log_file
  2. Tail the general log file
  3. Run the below with e.g 3 pages with 3 elements
  4. Observe that all ElementalArea.ID values for all 3 pages are in the query created by DataList::fetchEagerLoadHasMany()
$id = 3
$page = \Page::get()->byId($id);
$val = $page->getElementsForSearch();

Possible Solution

Don't use eager loading?

I was able to workaround the situation by providing an extension that extends ElementalPageExtension and just get the elements for the current page for the request. Unfortunately as getEagerLoadedElements is private, it can't be overridden so the two methods that call it need to be duplicated.

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)

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions