[BUGFIX] Cache calls to SchemaManager()->listTableColumns() 87/54087/2
authorStephan Großberndt <stephan@grossberndt.de>
Tue, 4 Jul 2017 07:51:55 +0000 (09:51 +0200)
committerBenni Mack <benni@typo3.org>
Sat, 9 Sep 2017 21:33:25 +0000 (23:33 +0200)
Caching the calls SchemaManager()->listTableColumns() during runtime
leads to improved performance when doing operations on multiple files or
multiple extbase Domain/Model objects at once as the same information
does not have to be fetched over and over.

Releases: master, 8.7
Resolves: #81778
Change-Id: Ieebcf5046d007dfea40acf148045807053873ac8
Reviewed-on: https://review.typo3.org/54087
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Benni Mack <benni@typo3.org>
Tested-by: Benni Mack <benni@typo3.org>
typo3/sysext/core/Classes/Resource/ProcessedFileRepository.php
typo3/sysext/extbase/Classes/Persistence/Generic/Storage/Typo3DbBackend.php

index dd63afc..9443c98 100644 (file)
@@ -42,6 +42,14 @@ class ProcessedFileRepository extends AbstractRepository
     protected $table = 'sys_file_processedfile';
 
     /**
     protected $table = 'sys_file_processedfile';
 
     /**
+     * As determining the table columns is a costly operation this is done only once during runtime and cached then
+     *
+     * @var array
+     * @see cleanUnavailableColumns()
+     */
+    protected $tableColumns = [];
+
+    /**
      * Creates this object.
      */
     public function __construct()
      * Creates this object.
      */
     public function __construct()
@@ -291,11 +299,15 @@ class ProcessedFileRepository extends AbstractRepository
      */
     protected function cleanUnavailableColumns(array $data)
     {
      */
     protected function cleanUnavailableColumns(array $data)
     {
-        $tableColumns = GeneralUtility::makeInstance(ConnectionPool::class)
-            ->getConnectionForTable($this->table)
-            ->getSchemaManager()
-            ->listTableColumns($this->table);
-        return array_intersect_key($data, $tableColumns);
+        // As determining the table columns is a costly operation this is done only once during runtime and cached then
+        if (empty($this->tableColumns[$this->table])) {
+            $this->tableColumns[$this->table] = GeneralUtility::makeInstance(ConnectionPool::class)
+                ->getConnectionForTable($this->table)
+                ->getSchemaManager()
+                ->listTableColumns($this->table);
+        }
+
+        return array_intersect_key($data, $this->tableColumns[$this->table]);
     }
 
     /**
     }
 
     /**
index 16a39dc..d5d35d8 100644 (file)
@@ -79,6 +79,14 @@ class Typo3DbBackend implements BackendInterface, SingletonInterface
     protected $objectManager;
 
     /**
     protected $objectManager;
 
     /**
+     * As determining the table columns is a costly operation this is done only once per table during runtime and cached then
+     *
+     * @var array
+     * @see clearPageCache()
+     */
+    protected $hasPidColumn = [];
+
+    /**
      * @param \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper $dataMapper
      */
     public function injectDataMapper(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper $dataMapper)
      * @param \TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper $dataMapper
      */
     public function injectDataMapper(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper $dataMapper)
@@ -678,11 +686,17 @@ class Typo3DbBackend implements BackendInterface, SingletonInterface
         }
         $pageIdsToClear = [];
         $storagePage = null;
         }
         $pageIdsToClear = [];
         $storagePage = null;
-        $columns = GeneralUtility::makeInstance(ConnectionPool::class)
-            ->getConnectionForTable($tableName)
-            ->getSchemaManager()
-            ->listTableColumns($tableName);
-        if (array_key_exists('pid', $columns)) {
+
+        // As determining the table columns is a costly operation this is done only once per table during runtime and cached then
+        if (!isset($this->hasPidColumn[$tableName])) {
+            $columns = GeneralUtility::makeInstance(ConnectionPool::class)
+                ->getConnectionForTable($tableName)
+                ->getSchemaManager()
+                ->listTableColumns($tableName);
+            $this->hasPidColumn[$tableName] = array_key_exists('pid', $columns);
+        }
+
+        if ($this->hasPidColumn[$tableName]) {
             $queryBuilder = $this->connectionPool->getQueryBuilderForTable($tableName);
             $queryBuilder->getRestrictions()->removeAll();
             $result = $queryBuilder
             $queryBuilder = $this->connectionPool->getQueryBuilderForTable($tableName);
             $queryBuilder->getRestrictions()->removeAll();
             $result = $queryBuilder