Skip to content
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

[RFC] Use the PageModel instead of direct SQL queries in button callbacks #1090

Closed

Conversation

agoat
Copy link
Contributor

@agoat agoat commented Sep 19, 2017

This PR handles the optimisation of button callbacks mentioned in #1089.

Is there a reason why all the button callbacks don't use Models??
Because if we will do, the amount of SQL Queries will drop from 415 to around 210 in the article view of the official contao demo page.

Currently every rendered article row will call the buttons callbacks which itself will make the same SQL Query to the tl_page table for every page (around 6 queries per article).

When the \PageModel is used, the Result is cached.

@Toflar
Copy link
Member

Toflar commented Sep 19, 2017

There is no reason and this is an excellent PR, thank you very much!

$objSubpages = $this->Database->prepare("SELECT * FROM tl_page WHERE pid=?")
->limit(1)
->execute($row['id']);
$objSubpages = \PageModel::findByPid($row['id'], array('limit'=>1));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could actually use countBy here, because we only need to know if there are subpages.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But then it's not read from the model registry and an extra sql query is executed (see Model.php).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well it does not read from the registry this way either... findByPid is not cacheable, and nothing is cacheable if you use options.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're totally right. It's only read from registry if a model is requested by it's id.

But one question is left: Is there a (measurable) difference in performance, when setting a limit of one or query all child records and count them?

I don't think so. The amount of data from the sql server is negligible unless someone have a thousand sub pages. So I'm fine with using countBy. Looks more logic.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to the countByPid method in b89e330

@leofeyer leofeyer added this to the 4.5.0 milestone Sep 20, 2017
@agoat agoat force-pushed the fix/reduceSqlQueriesOnTableCallbacks branch from bc5dd53 to b62d2fb Compare October 8, 2017 11:07
Copy link
Member

@leofeyer leofeyer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This kind of optimization applies to more than just tl_article and tl_page, does it?

$objPage = $this->Database->prepare("SELECT * FROM tl_page WHERE id=?")
->limit(1)
->execute($row['pid']);
$objPage = \PageModel::findById($row['pid']);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The namespace prefix is not necessary here.

$objPage = $this->Database->prepare("SELECT * FROM " . $table . " WHERE id=?")
->limit(1)
->execute(Input::get('id'));
$objPage = \PageModel::findById(Input::get('id'));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is wrong. You have to use the model that corresponds to $table.

$objPage = $this->Database->prepare("SELECT * FROM " . $table . " WHERE id=?")
->limit(1)
->execute($row['pid']);
$objPage = \PageModel::findById($row['pid']);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

$objSubpages = $this->Database->prepare("SELECT * FROM tl_page WHERE pid=?")
->limit(1)
->execute($row['id']);
$subPages = \PageModel::countByPid($row['id']);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has no effect. If you want to reuse the existing model, you have to use findByPid() here.

@leofeyer
Copy link
Member

Implemented in 57e2b6f. Thank you @agoat for analyzing this and pointing me in the right direction.

@leofeyer leofeyer closed this Nov 27, 2017
@agoat
Copy link
Contributor Author

agoat commented Nov 27, 2017

You're welcome.
Sorry, I didn't have time to look at this PR again. However, you know the core code better anyway and have found even more optimizations. Perfect.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants