[Standalone] Unnecessary queries
Grafikart opened this issue · comments
I post this issue here since I'm trying to use CakePHP ORM without Cakephp Core.
Is there a way to avoid unnecessary queries ? If I try to get 10 rows from a table CakePHP ORM will do 4 queries to get the structure of my table, even if log is turned off.
Is there a way to prevent this ? If so it would be nice to document it (I tried setting various informations in my Table class but nothing worked so far).
Here is the code I tried and the queries that it generates
ConnectionManager::config('default', [
.....
'log' => true
]);
$connection = ConnectionManager::get('default');
$logger = new QueryLogger();
$connection->logger($logger);
$tutoriels = new TutorielsTable(['connection' => $connection]);
$tutoriels->find()->limit(10)->toArray();
var_dump($logger->getQueries());
Array (size=5)
0 =>
array (size=3)
'query' => string 'SHOW FULL COLUMNS FROM `tutoriels`' (length=34)
'took' => float 2
'rows' => int 26
1 =>
array (size=3)
'query' => string 'SHOW INDEXES FROM `tutoriels`' (length=29)
'took' => float 0
'rows' => int 5
2 =>
array (size=3)
'query' => string 'SELECT * FROM information_schema.key_column_usage AS kcu
INNER JOIN information_schema.referential_constraints AS rc
ON (kcu.CONSTRAINT_NAME = rc.CONSTRAINT_NAME)
WHERE kcu.TABLE_SCHEMA = 'my_table' AND kcu.TABLE_NAME = 'tutoriels' and rc.TABLE_NAME = 'tutoriels'' (length=301)
'took' => float 0
'rows' => int 0
3 =>
array (size=3)
'query' => string 'SHOW TABLE STATUS WHERE Name = 'tutoriels'' (length=42)
'took' => float 0
'rows' => int 1
4 =>
array (size=3)
'query' => string 'SELECT Tutoriels.id AS `Tutoriels__id`, Tutoriels.name AS `Tutoriels__name`, Tutoriels.content AS `Tutoriels__content`, Tutoriels.content_markdown AS `Tutoriels__content_markdown`, Tutoriels.tp AS `Tutoriels__tp`, Tutoriels.duration AS `Tutoriels__duration`, Tutoriels.vimeo AS `Tutoriels__vimeo`, Tutoriels.daily AS `Tutoriels__daily`, Tutoriels.youtube AS `Tutoriels__youtube`, Tutoriels.blip AS `Tutoriels__blip`, Tutoriels.video AS `Tutoriels__video`, Tutoriels.video_size AS `Tutoriels__video_size`, Tutoriels.source AS `Tutoriels__source`, Tutoriels.demo AS `Tutoriels__demo`, Tutoriels.slug AS `Tutoriels__slug`, Tutoriels.category_id AS `Tutoriels__category_id`, Tutoriels.created AS `Tutoriels__created`, Tutoriels.comment_count AS `Tutoriels__comment_count`, Tutoriels.online AS `Tutoriels__online`, Tutoriels.premium AS `Tutoriels__premium`, Tutoriels.relative AS `Tutoriels__relative`, Tutoriels.serie AS `Tutoriels__serie`, Tutoriels.user_id AS `Tutoriels__user_id`, Tutoriels.lvl AS `Tutoriels__lvl`, Tutoriels.formation_id AS `Tutoriels__formation_id`, Tutoriels.color AS `Tutoriels__color` FROM tutoriels Tutoriels LIMIT 10' (length=1139)
'took' => float 0
'rows' => int 10
You'll need to cache the schema reflection. You can do this in one of a few ways:
- Install the cakephp/cache package and enable
cacheMetadata
in your connection definition. - Create a subclass of
Cake\Database\Schema\Collection
that caches the results ofdescribe()
. TheCachedCollection
class in the Database package is an example of this. This subclass can be injected into the connection usingConnection::schemaCollection($collection)
.
While the queries look superfluous, they are necessary so the ORM knows which columns can be selected, and the column types when generating insert/update queries.
Ok thanks that was what I was looking for. If someone is looking at this issue here is the solution :
\Cake\Cache\Cache::config('_cake_model_', [
'className' => 'File',
'duration' => '+1 hours',
'path' => 'tmp',
'prefix' => 'my_app_'
]);
And then enable cache for the connection
ConnectionManager::config('default', [
...
'cacheMetadata' => true
]);