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

Bad performance when moving objects to folders with lots of siblings #4332

Closed
BlackbitNeueMedien opened this issue May 8, 2019 · 0 comments

Comments

Projects
None yet
1 participant
@BlackbitNeueMedien
Copy link
Contributor

commented May 8, 2019

When you move a data object to a folder which already contains a lot of objects the performance is really slow - or in other words the system breaks down.

Steps to reproduce:

  1. Take a folder which contains about 10.000 objects
  2. Create an object outside of this folder
  3. Move the object via drag-and-drop to the folder
  4. In my example the AJAX request to /admin/object/update needed 292 seconds

The cause is this function:

protected function updateIndexesOfObjectSiblings(DataObject\AbstractObject $updatedObject, $newIndex)
{
$updateLatestVersionIndex = function ($object, $newIndex) {
if ($object instanceof DataObject\Concrete && $latestVersion = $object->getLatestVersion()) {
$object = $latestVersion->loadData();
$object->setIndex($newIndex);
$latestVersion->save();
}
};
$updatedObject->saveIndex($newIndex);
$list = new DataObject\Listing();
$list->setCondition(
'o_parentId = ? AND o_id != ?',
[$updatedObject->getParentId(), $updatedObject->getId()]
);
$list->setObjectTypes([DataObject\AbstractObject::OBJECT_TYPE_OBJECT, DataObject\AbstractObject::OBJECT_TYPE_VARIANT, DataObject\AbstractObject::OBJECT_TYPE_FOLDER]);
$list->setOrderKey('o_index');
$list->setOrder('asc');
$siblings = $list->load();
$index = 0;
/** @var DataObject\AbstractObject $child */
foreach ($siblings as $sibling) {
if ($index == $newIndex) {
$index++;
}
$sibling->saveIndex($index);
$updateLatestVersionIndex($sibling, $index);
$index++;
}
}

In this function all sibling objects are fetched and their o_index gets updated. This results in 10.000 update statements to be executed - of course this takes some time.

I do not really now what the o_index column is for - I thought of sorting by index vs. sorting by key but my folders are all sort by key, so updating the index would not be necessary.

My naive approach would be:

protected function updateIndexesOfObjectSiblings(DataObject\AbstractObject $updatedObject, $newIndex)
    {
        $updatedObject->saveIndex($newIndex);

        $list = new DataObject\Listing();
        Db::get()->executeUpdate('UPDATE '.$list->getDao()->getTableName().' SET o_index = o_index+1 WHERE o_parentId = ? AND o_id != ? AND o_index > ?', [$updatedObject->getParentId(), $updatedObject->getId(), $newIndex]);
    }

But I did not dare to put this in a PR because I am certainly missing some point why it is currently implemented by updating all siblings separately.
But even if this naive approach is not useful we need to find a way to accelerate moving an object to a folder with lots of objects.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.