mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-23 08:02:02 +00:00
Merge pull request #53797 from ClickHouse/add_profile_event_for_lock
Add event for tracking data parts lock
This commit is contained in:
commit
684d5aab88
@ -258,6 +258,8 @@ The server successfully detected this situation and will download merged part fr
|
|||||||
M(RWLockReadersWaitMilliseconds, "Total time spent waiting for a read lock to be acquired (in a heavy RWLock).") \
|
M(RWLockReadersWaitMilliseconds, "Total time spent waiting for a read lock to be acquired (in a heavy RWLock).") \
|
||||||
M(RWLockWritersWaitMilliseconds, "Total time spent waiting for a write lock to be acquired (in a heavy RWLock).") \
|
M(RWLockWritersWaitMilliseconds, "Total time spent waiting for a write lock to be acquired (in a heavy RWLock).") \
|
||||||
M(DNSError, "Total count of errors in DNS resolution") \
|
M(DNSError, "Total count of errors in DNS resolution") \
|
||||||
|
M(PartsLockHoldMicroseconds, "Total time spent holding data parts lock in MergeTree tables") \
|
||||||
|
M(PartsLockWaitMicroseconds, "Total time spent waiting for data parts lock in MergeTree tables") \
|
||||||
\
|
\
|
||||||
M(RealTimeMicroseconds, "Total (wall clock) time spent in processing (queries and other tasks) threads (note that this is a sum).") \
|
M(RealTimeMicroseconds, "Total (wall clock) time spent in processing (queries and other tasks) threads (note that this is a sum).") \
|
||||||
M(UserTimeMicroseconds, "Total time spent in processing (queries and other tasks) threads executing CPU instructions in user mode. This include time CPU pipeline was stalled due to main memory access, cache misses, branch mispredictions, hyper-threading, etc.") \
|
M(UserTimeMicroseconds, "Total time spent in processing (queries and other tasks) threads executing CPU instructions in user mode. This include time CPU pipeline was stalled due to main memory access, cache misses, branch mispredictions, hyper-threading, etc.") \
|
||||||
|
@ -132,6 +132,8 @@ namespace ProfileEvents
|
|||||||
extern const Event RejectedMutations;
|
extern const Event RejectedMutations;
|
||||||
extern const Event DelayedMutations;
|
extern const Event DelayedMutations;
|
||||||
extern const Event DelayedMutationsMilliseconds;
|
extern const Event DelayedMutationsMilliseconds;
|
||||||
|
extern const Event PartsLockWaitMicroseconds;
|
||||||
|
extern const Event PartsLockHoldMicroseconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace CurrentMetrics
|
namespace CurrentMetrics
|
||||||
@ -312,6 +314,20 @@ void MergeTreeData::initializeDirectoriesAndFormatVersion(const std::string & re
|
|||||||
throw Exception(ErrorCodes::METADATA_MISMATCH, "MergeTree data format version on disk doesn't support custom partitioning");
|
throw Exception(ErrorCodes::METADATA_MISMATCH, "MergeTree data format version on disk doesn't support custom partitioning");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
DataPartsLock::DataPartsLock(std::mutex & data_parts_mutex_)
|
||||||
|
: wait_watch(Stopwatch(CLOCK_MONOTONIC))
|
||||||
|
, lock(data_parts_mutex_)
|
||||||
|
, lock_watch(Stopwatch(CLOCK_MONOTONIC))
|
||||||
|
{
|
||||||
|
ProfileEvents::increment(ProfileEvents::PartsLockWaitMicroseconds, wait_watch->elapsedMicroseconds());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DataPartsLock::~DataPartsLock()
|
||||||
|
{
|
||||||
|
if (lock_watch.has_value())
|
||||||
|
ProfileEvents::increment(ProfileEvents::PartsLockHoldMicroseconds, lock_watch->elapsedMicroseconds());
|
||||||
|
}
|
||||||
|
|
||||||
MergeTreeData::MergeTreeData(
|
MergeTreeData::MergeTreeData(
|
||||||
const StorageID & table_id_,
|
const StorageID & table_id_,
|
||||||
@ -6268,14 +6284,14 @@ void MergeTreeData::Transaction::clear()
|
|||||||
precommitted_parts.clear();
|
precommitted_parts.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
MergeTreeData::DataPartsVector MergeTreeData::Transaction::commit(MergeTreeData::DataPartsLock * acquired_parts_lock)
|
MergeTreeData::DataPartsVector MergeTreeData::Transaction::commit(DataPartsLock * acquired_parts_lock)
|
||||||
{
|
{
|
||||||
DataPartsVector total_covered_parts;
|
DataPartsVector total_covered_parts;
|
||||||
|
|
||||||
if (!isEmpty())
|
if (!isEmpty())
|
||||||
{
|
{
|
||||||
auto settings = data.getSettings();
|
auto settings = data.getSettings();
|
||||||
auto parts_lock = acquired_parts_lock ? MergeTreeData::DataPartsLock() : data.lockParts();
|
auto parts_lock = acquired_parts_lock ? DataPartsLock() : data.lockParts();
|
||||||
auto * owing_parts_lock = acquired_parts_lock ? acquired_parts_lock : &parts_lock;
|
auto * owing_parts_lock = acquired_parts_lock ? acquired_parts_lock : &parts_lock;
|
||||||
|
|
||||||
for (const auto & part : precommitted_parts)
|
for (const auto & part : precommitted_parts)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
#include <base/defines.h>
|
#include <base/defines.h>
|
||||||
#include <Common/SimpleIncrement.h>
|
#include <Common/SimpleIncrement.h>
|
||||||
#include <Common/SharedMutex.h>
|
#include <Common/SharedMutex.h>
|
||||||
@ -40,7 +41,6 @@
|
|||||||
#include <boost/multi_index/global_fun.hpp>
|
#include <boost/multi_index/global_fun.hpp>
|
||||||
#include <boost/range/iterator_range_core.hpp>
|
#include <boost/range/iterator_range_core.hpp>
|
||||||
|
|
||||||
|
|
||||||
namespace DB
|
namespace DB
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -84,6 +84,16 @@ namespace ErrorCodes
|
|||||||
extern const int LOGICAL_ERROR;
|
extern const int LOGICAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct DataPartsLock
|
||||||
|
{
|
||||||
|
std::optional<Stopwatch> wait_watch;
|
||||||
|
std::unique_lock<std::mutex> lock;
|
||||||
|
std::optional<Stopwatch> lock_watch;
|
||||||
|
DataPartsLock() = default;
|
||||||
|
explicit DataPartsLock(std::mutex & data_parts_mutex_);
|
||||||
|
|
||||||
|
~DataPartsLock();
|
||||||
|
};
|
||||||
|
|
||||||
/// Data structure for *MergeTree engines.
|
/// Data structure for *MergeTree engines.
|
||||||
/// Merge tree is used for incremental sorting of data.
|
/// Merge tree is used for incremental sorting of data.
|
||||||
@ -220,7 +230,6 @@ public:
|
|||||||
using MutableDataParts = std::set<MutableDataPartPtr, LessDataPart>;
|
using MutableDataParts = std::set<MutableDataPartPtr, LessDataPart>;
|
||||||
using DataPartsVector = std::vector<DataPartPtr>;
|
using DataPartsVector = std::vector<DataPartPtr>;
|
||||||
|
|
||||||
using DataPartsLock = std::unique_lock<std::mutex>;
|
|
||||||
DataPartsLock lockParts() const { return DataPartsLock(data_parts_mutex); }
|
DataPartsLock lockParts() const { return DataPartsLock(data_parts_mutex); }
|
||||||
|
|
||||||
using OperationDataPartsLock = std::unique_lock<std::mutex>;
|
using OperationDataPartsLock = std::unique_lock<std::mutex>;
|
||||||
@ -240,7 +249,7 @@ public:
|
|||||||
public:
|
public:
|
||||||
Transaction(MergeTreeData & data_, MergeTreeTransaction * txn_);
|
Transaction(MergeTreeData & data_, MergeTreeTransaction * txn_);
|
||||||
|
|
||||||
DataPartsVector commit(MergeTreeData::DataPartsLock * acquired_parts_lock = nullptr);
|
DataPartsVector commit(DataPartsLock * acquired_parts_lock = nullptr);
|
||||||
|
|
||||||
void addPart(MutableDataPartPtr & part);
|
void addPart(MutableDataPartPtr & part);
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ void MergeTreeWriteAheadLog::rotate(const std::unique_lock<std::mutex> &)
|
|||||||
MergeTreeData::MutableDataPartsVector MergeTreeWriteAheadLog::restore(
|
MergeTreeData::MutableDataPartsVector MergeTreeWriteAheadLog::restore(
|
||||||
const StorageMetadataPtr & metadata_snapshot,
|
const StorageMetadataPtr & metadata_snapshot,
|
||||||
ContextPtr context,
|
ContextPtr context,
|
||||||
std::unique_lock<std::mutex> & parts_lock,
|
DataPartsLock & parts_lock,
|
||||||
bool readonly)
|
bool readonly)
|
||||||
{
|
{
|
||||||
std::unique_lock lock(write_mutex);
|
std::unique_lock lock(write_mutex);
|
||||||
|
@ -11,6 +11,7 @@ namespace DB
|
|||||||
{
|
{
|
||||||
|
|
||||||
class MergeTreeData;
|
class MergeTreeData;
|
||||||
|
struct DataPartsLock;
|
||||||
|
|
||||||
/** WAL stores addditions and removals of data parts in in-memory format.
|
/** WAL stores addditions and removals of data parts in in-memory format.
|
||||||
* Format of data in WAL:
|
* Format of data in WAL:
|
||||||
@ -64,7 +65,7 @@ public:
|
|||||||
std::vector<MergeTreeMutableDataPartPtr> restore(
|
std::vector<MergeTreeMutableDataPartPtr> restore(
|
||||||
const StorageMetadataPtr & metadata_snapshot,
|
const StorageMetadataPtr & metadata_snapshot,
|
||||||
ContextPtr context,
|
ContextPtr context,
|
||||||
std::unique_lock<std::mutex> & parts_lock,
|
DataPartsLock & parts_lock,
|
||||||
bool readonly);
|
bool readonly);
|
||||||
|
|
||||||
using MinMaxBlockNumber = std::pair<Int64, Int64>;
|
using MinMaxBlockNumber = std::pair<Int64, Int64>;
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
1
|
16
tests/queries/0_stateless/02864_profile_event_part_lock.sql
Normal file
16
tests/queries/0_stateless/02864_profile_event_part_lock.sql
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
DROP TABLE IF EXISTS random_mt;
|
||||||
|
|
||||||
|
CREATE TABLE random_mt
|
||||||
|
(
|
||||||
|
key UInt64,
|
||||||
|
value String
|
||||||
|
)
|
||||||
|
ENGINE MergeTree()
|
||||||
|
ORDER BY tuple();
|
||||||
|
|
||||||
|
INSERT INTO random_mt VALUES (1, 'Hello');
|
||||||
|
|
||||||
|
SELECT any(value > 0) from system.events WHERE event = 'PartsLockHoldMicroseconds' or event = 'PartsLockWaitMicroseconds';
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS random_mt;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user