Reputation: 1
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
Upvotes: 0
Views: 277
Reputation: 65
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.
Upvotes: 0