简体   繁体   中英

Typo3 Performance in Extbase Model

so, I have a performance issue with my extbase plugin. The scenario is such: I have 4 database tables with data for artists, artworks, exhibitions and publications. Exhibitions can have artists, artworks and publications as mm relations. publications and artwork can have artists as mm relations. In my Model Classes I have those relations as ObjectStorage and use simple findAll() Method for my List View. So if I get to the Exhibition List View I get every Exhibition and their related Artists and all related Artworks/Publications/Exhibitions of that Artist. The performance is really bad and a not cached page needs almost a full minute to load. And this is all because of the heavy data load from the db. I only need the MM relations on the first level and not further. Is there anyway to config this?

Classes\Domain\Model\Exhibition.php

class Exhibition extends AbstractEntity
{

    /**
     * @var string
     */
    protected $name = '';

    /**
     * @var string
     */
    protected $location = '';

    /**
     * artists
     *
     * @var ObjectStorage<\Vendor\Project\Domain\Model\Artist>
     * @TYPO3\CMS\Extbase\Annotation\ORM\Lazy
     */
    protected $artists = null;

    /**
     * artworks
     *
     * @var ObjectStorage<\Vendor\Project\Domain\Model\Artwork>
     * @TYPO3\CMS\Extbase\Annotation\ORM\Lazy
     */
    protected $artworks;

    /**
     * publications
     *
     * @var ObjectStorage<\Vendor\Project\Domain\Model\Publication>
     * @TYPO3\CMS\Extbase\Annotation\ORM\Lazy
     */
    protected $publications;

    /**
     * Fal media items
     *
     * @var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\FileReference>
     * @TYPO3\CMS\Extbase\Annotation\ORM\Lazy
     */
    protected $falMedia;


    public function __construct(string $name = '', string $description = '', string $location = '')
    {
        $this->setName($name);
        $this->setLocation($location);
    }

    /**
     * @param string $name
     */
    public function setName(string $name): void
    {
        $this->name = $name;
    }

    /**
     * @return string
     */
    public function getName(): string
    {
        return $this->name;
    }

    /**
     * @return string
     */
    public function getLocation(): string
    {
        return $this->location;
    }

    /**
     * @param string $location
     */
    public function setLocation(string $location): void
    {
        $this->location = $location;
    }

    /**
     * Returns the artist
     *
     * @return ObjectStorage<\Vendor\Project\Domain\Model\Artist> $artists
     */
    public function getArtists()
    {
        return $this->artists;
    }

    /**
     * Sets the artist
     *
     * @param ObjectStorage<\Vendor\GKG\Domain\Model\Artist> $artists
     * @return void
     */
    public function setArtists(ObjectStorage $artists)
    {
        $this->artists = $artists;
    }

    /**
     * @param $artworks
     */
    public function setArtworks($artworks)
    {
        $this->artworks = $artworks;
    }

    /**
     * @return ObjectStorage
     */
    public function getArtworks()
    {
        return $this->artworks;
    }

    /**
     * Sets the publications
     *
     * @param ObjectStorage<\Vendor\Project\Domain\Model\Publication> $oublications
     * @return void
     */
    public function setPublications(ObjectStorage $publications)
    {
        $this->publications = $publications;
    }

    /**
     * Returns the publications
     *
     * @return ObjectStorage<\Vendor\Project\Domain\Model\Publication> $publications
     */
    public function getPublications()
    {
        return $this->publications;
    }

    /**
     * Get the Fal media items
     *
     * @return \TYPO3\CMS\Extbase\Persistence\ObjectStorage
     */
    public function getFalMedia()
    {
        return $this->falMedia;
    }

}

This gets all the Artist data in which all related data is fetched as well (artwork, exhibition and publication). And this is a heavy overload:/

I tried to write my own query and only select the values I need in my frontend: Classes\Domain\Repository\ExhibitionRepository.php

public function findExhibitions()
{
    $languageAspect = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance
    (\TYPO3\CMS\Core\Context\Context::class)->getAspect('language');
    $sys_language_uid = $languageAspect->getId();

    $query = $this->createQuery();
    $query->getQuerySettings()->setRespectSysLanguage(true);
    $query->statement( "
        SELECT DISTINCT     e.name, e.uid, e.location, e.fal_media, a.name, a.uid
        FROM        tx_project_domain_model_exhibition e
        LEFT JOIN   tx_project_exhibitions_artists_mm
        ON          tx_project_exhibitions_artists_mm.uid_local = e.uid
        LEFT JOIN   tx_project_domain_model_artist a
        ON          tx_project_exhibitions_artists_mm.uid_foreign = a.uid
        WHERE       e.sys_language_uid = $sys_language_uid
        GROUP BY    tx_project_exhibitions_artists_mm.uid_local
    " );
    return $query->execute();
}

But with this approach I'm not able to get the relation data to my assigned view variable inside my Controller. Only the exhibition related stuff.

Classes\Controller\ExhibitionController.php

public function indexAction()
{
    $queryResult = $this->exhibitionRepository->findExhibitions();
    $this->view->assign('exhibitions', $queryResult);
}

Any insight and advice on how to tackle this problem and only get the needed Data and not everything from the ObjectStorage?

Thanks in advance and best regards

It looks like your query cost is very high with all the JOINS and without a condition on a indexed column. You could check it with an EXPLAIN PLAN(MySQL) / EXECUTION PLAN(MS).

Another performance boost is to use Ajax, just search for "TYPO3 Ajax":

get an identifier and display it in the Frontend:

SELECT DISTINCT e. uid, e.name FROM tx_project_domain_model_exhibition

On identifier click (name or whatever) make a call of the AjaxController.php:

...
    $this->exhibitionRepository->findByUid($uid);
...

or make your own repository comparing

...
    $query->matching(
            $query->logicalAnd(
                 $query->equals('uid', $uid),
                 $query->equals('name', $name)
            )
    );
...

show the data on a Modal Window,Accordion or a new View.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM