The cache needs to return the same results as running the subquery would, so the scope has to be limited by active transaction too.
But seeing that the cache can only be enabled or disabled as an optimizer feature and not configured otherwise, my guess is that it actually is instantiated once for each specific cacheable subquery for a query where the optimizer decides it is worth it.
That seems to be confirmed by: "It has a unique index over all parameters." - this is not doable if you store results for more than one subquery in the same table.
So it seems to me that the cache is instantiated once for each cacheable subquery and its lifetime would be limited by the outer query execution.
Edit: I checked some source code (disclaimer: I definitely do not fully understand the code as MariaDB is quite big and complex piece of software and my knowledge of C++ is far from expert level). The cache is implemented by the Expression_cache_tmptable
. The table used to store the cached results is created in the init()
method which is being called from some methods in Item_cache_wrapper
and AFAIK lifespan of various Items is single (outer) query execution as different types of Items keep and manage different parts of the query (sort of expression tree if I understand it correctly).
From that I deduce that one instance of the subquery cache is created for each cacheable subquery at the time query is being "prepared" for execution. It is then initialized (and the temp table created) when it is first accessed during the query execution (so only if the subquery is actually executed at least once). The condition of "<0.2" is then checked (for each subquery independently) after 200 misses (that will probably be after processing some 200+ rows of the outer query) to see if the cache has any positive effect, and it is disabled early if it does not help. Then, if the cache table grows too much, it is checked again according to the conditions listed in the manual.
So the subquery cache is not tuneable, but seems to be made as unintrusive as possible. The optimizer will ever instantiate it for subqueries which can at least theoretically use it and it will be disabled early in the query execution if it does not prove useful.
If you are still worried about it slowing your queries down, you can disable it globally by configuring the optimizer_switch
and then enable it only for selected queries by calling
SET SESSION optimizer_switch='subquery_cache=on';
before the query execution and optionally turn it off afterwards.
tmp
is used when mysql/mariadb
engine can't use ENGINE=MEMORY
for temporary tables. That happens for many reasons:
Temporary table is too big to fit into join/sort
buffer. That may
be caused by too small buffers or by queries that produce too big
results due to the bad design.
Temporary table contains text/blob fields that are not appropriate
for MEMORY engine.
Proper index(es) are missed for the query, so massive filesorts performed on the disk in the mysql/tmp dir.
Anyway as far as disk-based temp-tables are significantly slower than in-memory ones, queries that fill up the mysql/tmp
dir are listed in the slow queries log along with short diagnosis.
Best Answer
I think it is a bad idea to rob space in RAM for things other than
innodb_buffer_pool_size
.Furthermore, your example is flawed. An
ALTER
that needs to copy works this way:Step 2 is the issue: