mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-25 17:12:03 +00:00
Merge pull request #68710 from ClickHouse/backport/24.8/68477
Backport #68477 to 24.8: Drop query cache by tag
This commit is contained in:
commit
9fe11c4df8
@ -155,6 +155,8 @@ SELECT 1 SETTINGS use_query_cache = true, query_cache_tag = 'tag 1';
|
|||||||
SELECT 1 SETTINGS use_query_cache = true, query_cache_tag = 'tag 2';
|
SELECT 1 SETTINGS use_query_cache = true, query_cache_tag = 'tag 2';
|
||||||
```
|
```
|
||||||
|
|
||||||
|
To remove only entries with tag `tag` from the query cache, you can use statement `SYSTEM DROP QUERY CACHE TAG 'tag'`.
|
||||||
|
|
||||||
ClickHouse reads table data in blocks of [max_block_size](settings/settings.md#setting-max_block_size) rows. Due to filtering, aggregation,
|
ClickHouse reads table data in blocks of [max_block_size](settings/settings.md#setting-max_block_size) rows. Due to filtering, aggregation,
|
||||||
etc., result blocks are typically much smaller than 'max_block_size' but there are also cases where they are much bigger. Setting
|
etc., result blocks are typically much smaller than 'max_block_size' but there are also cases where they are much bigger. Setting
|
||||||
[query_cache_squash_partial_results](settings/settings.md#query-cache-squash-partial-results) (enabled by default) controls if result blocks
|
[query_cache_squash_partial_results](settings/settings.md#query-cache-squash-partial-results) (enabled by default) controls if result blocks
|
||||||
|
@ -136,7 +136,13 @@ The compiled expression cache is enabled/disabled with the query/user/profile-le
|
|||||||
|
|
||||||
## DROP QUERY CACHE
|
## DROP QUERY CACHE
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SYSTEM DROP QUERY CACHE;
|
||||||
|
SYSTEM DROP QUERY CACHE TAG '<tag>'
|
||||||
|
````
|
||||||
|
|
||||||
Clears the [query cache](../../operations/query-cache.md).
|
Clears the [query cache](../../operations/query-cache.md).
|
||||||
|
If a tag is specified, only query cache entries with the specified tag are deleted.
|
||||||
|
|
||||||
## DROP FORMAT SCHEMA CACHE {#system-drop-schema-format}
|
## DROP FORMAT SCHEMA CACHE {#system-drop-schema-format}
|
||||||
|
|
||||||
|
@ -197,6 +197,12 @@ public:
|
|||||||
cache_policy->remove(key);
|
cache_policy->remove(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void remove(std::function<bool(const Key&, const MappedPtr &)> predicate)
|
||||||
|
{
|
||||||
|
std::lock_guard lock(mutex);
|
||||||
|
cache_policy->remove(predicate);
|
||||||
|
}
|
||||||
|
|
||||||
size_t sizeInBytes() const
|
size_t sizeInBytes() const
|
||||||
{
|
{
|
||||||
std::lock_guard lock(mutex);
|
std::lock_guard lock(mutex);
|
||||||
|
@ -55,6 +55,7 @@ public:
|
|||||||
virtual void set(const Key & key, const MappedPtr & mapped) = 0;
|
virtual void set(const Key & key, const MappedPtr & mapped) = 0;
|
||||||
|
|
||||||
virtual void remove(const Key & key) = 0;
|
virtual void remove(const Key & key) = 0;
|
||||||
|
virtual void remove(std::function<bool(const Key & key, const MappedPtr & mapped)> predicate) = 0;
|
||||||
|
|
||||||
virtual void clear() = 0;
|
virtual void clear() = 0;
|
||||||
virtual std::vector<KeyMapped> dump() const = 0;
|
virtual std::vector<KeyMapped> dump() const = 0;
|
||||||
|
@ -79,6 +79,22 @@ public:
|
|||||||
cells.erase(it);
|
cells.erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void remove(std::function<bool(const Key &, const MappedPtr &)> predicate) override
|
||||||
|
{
|
||||||
|
for (auto it = cells.begin(); it != cells.end();)
|
||||||
|
{
|
||||||
|
if (predicate(it->first, it->second.value))
|
||||||
|
{
|
||||||
|
Cell & cell = it->second;
|
||||||
|
current_size_in_bytes -= cell.size;
|
||||||
|
queue.erase(cell.queue_iterator);
|
||||||
|
it = cells.erase(it);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MappedPtr get(const Key & key) override
|
MappedPtr get(const Key & key) override
|
||||||
{
|
{
|
||||||
auto it = cells.find(key);
|
auto it = cells.find(key);
|
||||||
|
@ -95,6 +95,27 @@ public:
|
|||||||
cells.erase(it);
|
cells.erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void remove(std::function<bool(const Key &, const MappedPtr &)> predicate) override
|
||||||
|
{
|
||||||
|
for (auto it = cells.begin(); it != cells.end();)
|
||||||
|
{
|
||||||
|
if (predicate(it->first, it->second.value))
|
||||||
|
{
|
||||||
|
auto & cell = it->second;
|
||||||
|
|
||||||
|
current_size_in_bytes -= cell.size;
|
||||||
|
if (cell.is_protected)
|
||||||
|
current_protected_size -= cell.size;
|
||||||
|
|
||||||
|
auto & queue = cell.is_protected ? protected_queue : probationary_queue;
|
||||||
|
queue.erase(cell.queue_iterator);
|
||||||
|
it = cells.erase(it);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MappedPtr get(const Key & key) override
|
MappedPtr get(const Key & key) override
|
||||||
{
|
{
|
||||||
auto it = cells.find(key);
|
auto it = cells.find(key);
|
||||||
|
@ -145,6 +145,23 @@ public:
|
|||||||
size_in_bytes -= sz;
|
size_in_bytes -= sz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void remove(std::function<bool(const Key &, const MappedPtr &)> predicate) override
|
||||||
|
{
|
||||||
|
for (auto it = cache.begin(); it != cache.end();)
|
||||||
|
{
|
||||||
|
if (predicate(it->first, it->second))
|
||||||
|
{
|
||||||
|
size_t sz = weight_function(*it->second);
|
||||||
|
if (it->first.user_id.has_value())
|
||||||
|
Base::user_quotas->decreaseActual(*it->first.user_id, sz);
|
||||||
|
it = cache.erase(it);
|
||||||
|
size_in_bytes -= sz;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MappedPtr get(const Key & key) override
|
MappedPtr get(const Key & key) override
|
||||||
{
|
{
|
||||||
auto it = cache.find(key);
|
auto it = cache.find(key);
|
||||||
|
@ -619,9 +619,18 @@ QueryCache::Writer QueryCache::createWriter(const Key & key, std::chrono::millis
|
|||||||
return Writer(cache, key, max_entry_size_in_bytes, max_entry_size_in_rows, min_query_runtime, squash_partial_results, max_block_size);
|
return Writer(cache, key, max_entry_size_in_bytes, max_entry_size_in_rows, min_query_runtime, squash_partial_results, max_block_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QueryCache::clear()
|
void QueryCache::clear(const std::optional<String> & tag)
|
||||||
{
|
{
|
||||||
cache.clear();
|
if (tag)
|
||||||
|
{
|
||||||
|
auto predicate = [tag](const Key & key, const Cache::MappedPtr &) { return key.tag == tag.value(); };
|
||||||
|
cache.remove(predicate);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cache.clear();
|
||||||
|
}
|
||||||
|
|
||||||
std::lock_guard lock(mutex);
|
std::lock_guard lock(mutex);
|
||||||
times_executed.clear();
|
times_executed.clear();
|
||||||
}
|
}
|
||||||
|
@ -211,7 +211,7 @@ public:
|
|||||||
Reader createReader(const Key & key);
|
Reader createReader(const Key & key);
|
||||||
Writer createWriter(const Key & key, std::chrono::milliseconds min_query_runtime, bool squash_partial_results, size_t max_block_size, size_t max_query_cache_size_in_bytes_quota, size_t max_query_cache_entries_quota);
|
Writer createWriter(const Key & key, std::chrono::milliseconds min_query_runtime, bool squash_partial_results, size_t max_block_size, size_t max_query_cache_size_in_bytes_quota, size_t max_query_cache_entries_quota);
|
||||||
|
|
||||||
void clear();
|
void clear(const std::optional<String> & tag);
|
||||||
|
|
||||||
size_t sizeInBytes() const;
|
size_t sizeInBytes() const;
|
||||||
size_t count() const;
|
size_t count() const;
|
||||||
|
@ -3225,12 +3225,12 @@ QueryCachePtr Context::getQueryCache() const
|
|||||||
return shared->query_cache;
|
return shared->query_cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Context::clearQueryCache() const
|
void Context::clearQueryCache(const std::optional<String> & tag) const
|
||||||
{
|
{
|
||||||
std::lock_guard lock(shared->mutex);
|
std::lock_guard lock(shared->mutex);
|
||||||
|
|
||||||
if (shared->query_cache)
|
if (shared->query_cache)
|
||||||
shared->query_cache->clear();
|
shared->query_cache->clear(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Context::clearCaches() const
|
void Context::clearCaches() const
|
||||||
|
@ -1068,7 +1068,7 @@ public:
|
|||||||
void setQueryCache(size_t max_size_in_bytes, size_t max_entries, size_t max_entry_size_in_bytes, size_t max_entry_size_in_rows);
|
void setQueryCache(size_t max_size_in_bytes, size_t max_entries, size_t max_entry_size_in_bytes, size_t max_entry_size_in_rows);
|
||||||
void updateQueryCacheConfiguration(const Poco::Util::AbstractConfiguration & config);
|
void updateQueryCacheConfiguration(const Poco::Util::AbstractConfiguration & config);
|
||||||
std::shared_ptr<QueryCache> getQueryCache() const;
|
std::shared_ptr<QueryCache> getQueryCache() const;
|
||||||
void clearQueryCache() const;
|
void clearQueryCache(const std::optional<String> & tag) const;
|
||||||
|
|
||||||
/** Clear the caches of the uncompressed blocks and marks.
|
/** Clear the caches of the uncompressed blocks and marks.
|
||||||
* This is usually done when renaming tables, changing the type of columns, deleting a table.
|
* This is usually done when renaming tables, changing the type of columns, deleting a table.
|
||||||
|
@ -369,9 +369,12 @@ BlockIO InterpreterSystemQuery::execute()
|
|||||||
system_context->clearMMappedFileCache();
|
system_context->clearMMappedFileCache();
|
||||||
break;
|
break;
|
||||||
case Type::DROP_QUERY_CACHE:
|
case Type::DROP_QUERY_CACHE:
|
||||||
|
{
|
||||||
getContext()->checkAccess(AccessType::SYSTEM_DROP_QUERY_CACHE);
|
getContext()->checkAccess(AccessType::SYSTEM_DROP_QUERY_CACHE);
|
||||||
getContext()->clearQueryCache();
|
getContext()->clearQueryCache(query.query_cache_tag);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case Type::DROP_COMPILED_EXPRESSION_CACHE:
|
case Type::DROP_COMPILED_EXPRESSION_CACHE:
|
||||||
#if USE_EMBEDDED_COMPILER
|
#if USE_EMBEDDED_COMPILER
|
||||||
getContext()->checkAccess(AccessType::SYSTEM_DROP_COMPILED_EXPRESSION_CACHE);
|
getContext()->checkAccess(AccessType::SYSTEM_DROP_COMPILED_EXPRESSION_CACHE);
|
||||||
|
@ -130,6 +130,8 @@ public:
|
|||||||
String disk;
|
String disk;
|
||||||
UInt64 seconds{};
|
UInt64 seconds{};
|
||||||
|
|
||||||
|
std::optional<String> query_cache_tag;
|
||||||
|
|
||||||
String filesystem_cache_name;
|
String filesystem_cache_name;
|
||||||
std::string key_to_drop;
|
std::string key_to_drop;
|
||||||
std::optional<size_t> offset_to_drop;
|
std::optional<size_t> offset_to_drop;
|
||||||
|
@ -470,6 +470,7 @@ namespace DB
|
|||||||
MR_MACROS(TABLE_OVERRIDE, "TABLE OVERRIDE") \
|
MR_MACROS(TABLE_OVERRIDE, "TABLE OVERRIDE") \
|
||||||
MR_MACROS(TABLE, "TABLE") \
|
MR_MACROS(TABLE, "TABLE") \
|
||||||
MR_MACROS(TABLES, "TABLES") \
|
MR_MACROS(TABLES, "TABLES") \
|
||||||
|
MR_MACROS(TAG, "TAG") \
|
||||||
MR_MACROS(TAGS, "TAGS") \
|
MR_MACROS(TAGS, "TAGS") \
|
||||||
MR_MACROS(TAGS_INNER_UUID, "TAGS INNER UUID") \
|
MR_MACROS(TAGS_INNER_UUID, "TAGS INNER UUID") \
|
||||||
MR_MACROS(TEMPORARY_TABLE, "TEMPORARY TABLE") \
|
MR_MACROS(TEMPORARY_TABLE, "TEMPORARY TABLE") \
|
||||||
|
@ -470,6 +470,16 @@ bool ParserSystemQuery::parseImpl(IParser::Pos & pos, ASTPtr & node, Expected &
|
|||||||
res->seconds = seconds->as<ASTLiteral>()->value.safeGet<UInt64>();
|
res->seconds = seconds->as<ASTLiteral>()->value.safeGet<UInt64>();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case Type::DROP_QUERY_CACHE:
|
||||||
|
{
|
||||||
|
ParserLiteral tag_parser;
|
||||||
|
ASTPtr ast;
|
||||||
|
if (ParserKeyword{Keyword::TAG}.ignore(pos, expected) && tag_parser.parse(pos, ast, expected))
|
||||||
|
res->query_cache_tag = std::make_optional<String>(ast->as<ASTLiteral>()->value.safeGet<String>());
|
||||||
|
if (!parseQueryWithOnCluster(res, pos, expected))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case Type::DROP_FILESYSTEM_CACHE:
|
case Type::DROP_FILESYSTEM_CACHE:
|
||||||
{
|
{
|
||||||
ParserLiteral path_parser;
|
ParserLiteral path_parser;
|
||||||
|
@ -1,3 +1,17 @@
|
|||||||
|
Cache query result in query cache
|
||||||
1
|
1
|
||||||
1
|
1
|
||||||
|
DROP entries with a certain tag, no entry will match
|
||||||
|
1
|
||||||
|
After a full DROP, the cache is empty now
|
||||||
|
0
|
||||||
|
Cache query result with different or no tag in query cache
|
||||||
|
1
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
4
|
||||||
|
DROP entries with certain tags
|
||||||
|
2
|
||||||
|
1
|
||||||
0
|
0
|
||||||
|
@ -4,10 +4,31 @@
|
|||||||
-- (it's silly to use what will be tested below but we have to assume other tests cluttered the query cache)
|
-- (it's silly to use what will be tested below but we have to assume other tests cluttered the query cache)
|
||||||
SYSTEM DROP QUERY CACHE;
|
SYSTEM DROP QUERY CACHE;
|
||||||
|
|
||||||
-- Cache query result in query cache
|
SELECT 'Cache query result in query cache';
|
||||||
SELECT 1 SETTINGS use_query_cache = true;
|
SELECT 1 SETTINGS use_query_cache = true;
|
||||||
SELECT count(*) FROM system.query_cache;
|
SELECT count(*) FROM system.query_cache;
|
||||||
|
|
||||||
-- No query results are cached after DROP
|
SELECT 'DROP entries with a certain tag, no entry will match';
|
||||||
|
SYSTEM DROP QUERY CACHE TAG 'tag';
|
||||||
|
SELECT count(*) FROM system.query_cache;
|
||||||
|
|
||||||
|
SELECT 'After a full DROP, the cache is empty now';
|
||||||
SYSTEM DROP QUERY CACHE;
|
SYSTEM DROP QUERY CACHE;
|
||||||
SELECT count(*) FROM system.query_cache;
|
SELECT count(*) FROM system.query_cache;
|
||||||
|
|
||||||
|
-- More tests for DROP with tags:
|
||||||
|
|
||||||
|
SELECT 'Cache query result with different or no tag in query cache';
|
||||||
|
SELECT 1 SETTINGS use_query_cache = true;
|
||||||
|
SELECT 1 SETTINGS use_query_cache = true, query_cache_tag = 'abc';
|
||||||
|
SELECT 1 SETTINGS use_query_cache = true, query_cache_tag = 'def';
|
||||||
|
SELECT 2 SETTINGS use_query_cache = true;
|
||||||
|
SELECT count(*) FROM system.query_cache;
|
||||||
|
|
||||||
|
SELECT 'DROP entries with certain tags';
|
||||||
|
SYSTEM DROP QUERY CACHE TAG '';
|
||||||
|
SELECT count(*) FROM system.query_cache;
|
||||||
|
SYSTEM DROP QUERY CACHE TAG 'def';
|
||||||
|
SELECT count(*) FROM system.query_cache;
|
||||||
|
SYSTEM DROP QUERY CACHE TAG 'abc';
|
||||||
|
SELECT count(*) FROM system.query_cache;
|
||||||
|
Loading…
Reference in New Issue
Block a user