Skip to content

Commit 029ba78

Browse files
authored
Merge pull request ClickHouse#114146 from Avogar/respect-subcolumn-sizes-setting-in-prewhere
Respect allow_calculating_subcolumns_sizes_for_merge_tree_reading in PREWHERE optimization
2 parents 81a084f + 9a80830 commit 029ba78

13 files changed

Lines changed: 136 additions & 20 deletions

src/Interpreters/InterpreterSelectQuery.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ namespace Setting
135135
extern const SettingsMap additional_table_filters;
136136
extern const SettingsUInt64 aggregation_in_order_max_block_bytes;
137137
extern const SettingsUInt64 aggregation_memory_efficient_merge_threads;
138+
extern const SettingsBool allow_calculating_subcolumns_sizes_for_merge_tree_reading;
138139
extern const SettingsUInt64 allow_experimental_parallel_reading_from_replicas;
139140
extern const SettingsUInt64 automatic_parallel_replicas_mode;
140141
extern const SettingsBool async_socket_for_remote;
@@ -876,7 +877,9 @@ InterpreterSelectQuery::InterpreterSelectQuery(
876877
{
877878
/// PREWHERE optimization: transfer some condition from WHERE to PREWHERE if enabled and viable
878879
Names queried_columns = syntax_analyzer_result->requiredSourceColumns();
879-
if (const auto & column_sizes = storage->getColumnSizes(queried_columns); !column_sizes.empty())
880+
const auto & column_sizes = storage->getColumnSizes(
881+
queried_columns, context->getSettingsRef()[Setting::allow_calculating_subcolumns_sizes_for_merge_tree_reading]);
882+
if (!column_sizes.empty())
880883
{
881884
/// Extract column compressed sizes.
882885
std::unordered_map<std::string, UInt64> column_compressed_sizes;

src/Processors/QueryPlan/Optimizations/optimizePrewhere.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ namespace DB
2222
{
2323
namespace Setting
2424
{
25+
extern const SettingsBool allow_calculating_subcolumns_sizes_for_merge_tree_reading;
2526
extern const SettingsBool optimize_move_to_prewhere;
2627
extern const SettingsBool optimize_move_to_prewhere_if_final;
2728
extern const SettingsBool optimize_prewhere_after_pushdown;
@@ -224,7 +225,8 @@ void optimizePrewhere(QueryPlan::Node & parent_node, const bool remove_unused_co
224225

225226
const auto & queried_columns = source_step_with_filter->requiredSourceColumns();
226227

227-
auto column_sizes = storage.getColumnSizes(queried_columns);
228+
auto column_sizes = storage.getColumnSizes(
229+
queried_columns, settings[Setting::allow_calculating_subcolumns_sizes_for_merge_tree_reading]);
228230
if (column_sizes.empty())
229231
return;
230232

src/Storages/IStorage.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,9 +216,12 @@ class IStorage : public std::enable_shared_from_this<IStorage>, public TypePromo
216216
using ColumnSizeByName = std::unordered_map<std::string, ColumnSize>;
217217
virtual ColumnSizeByName getColumnSizes() const { return {}; }
218218

219-
/// Same as parameterless overload but also includes sizes for requested subcolumns
219+
/// Same as parameterless overload but also includes sizes for the requested subcolumns.
220+
/// Computing exact subcolumn sizes can be expensive, so `calculate_subcolumn_sizes` (driven by
221+
/// `allow_calculating_subcolumns_sizes_for_merge_tree_reading` at call sites) selects between the
222+
/// exact size and the cheaper top-level column size as an approximation.
220223
/// The default implementation falls back to the parameterless version.
221-
virtual ColumnSizeByName getColumnSizes(const Names & /*columns*/) const { return getColumnSizes(); }
224+
virtual ColumnSizeByName getColumnSizes(const Names & /*columns*/, bool /*calculate_subcolumn_sizes*/) const { return getColumnSizes(); }
222225

223226
/// Same as getColumnSizes() but may return nullopt in some specific engines like Merge/Alias
224227
virtual std::optional<ColumnSizeByName> tryGetColumnSizes() const { return getColumnSizes(); }

src/Storages/MergeTree/MergeTreeData.cpp

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7760,7 +7760,7 @@ void MergeTreeData::addPartContributionToColumnAndSecondaryIndexSizesUnlocked(co
77607760
primary_index_size.add(part->getIndexSizeFromFile());
77617761
}
77627762

7763-
IStorage::ColumnSizeByName MergeTreeData::getColumnSizes(const Names & columns) const
7763+
IStorage::ColumnSizeByName MergeTreeData::getColumnSizes(const Names & columns, bool calculate_subcolumn_sizes) const
77647764
{
77657765
auto result = getColumnSizes();
77667766

@@ -7777,12 +7777,36 @@ IStorage::ColumnSizeByName MergeTreeData::getColumnSizes(const Names & columns)
77777777
if (subcolumn_names.empty())
77787778
return result;
77797779

7780-
/// For each requested column that is a subcolumn and not already in the result,
7781-
/// aggregate its size across all active parts using getSubcolumnSize.
7782-
/// This gives the correct on-disk size for subcolumns based on required substreams.
7783-
auto parts_lock = readLockParts();
7784-
auto committed_parts_range = getDataPartsStateRange(DataPartState::Active);
7785-
for (const auto & part : committed_parts_range)
7780+
/// When exact subcolumn sizes are disabled, approximate each subcolumn with its whole top-level
7781+
/// column size (already in result), resolved from metadata without locking parts.
7782+
if (!calculate_subcolumn_sizes)
7783+
{
7784+
auto metadata_snapshot = getInMemoryMetadataPtr(getContext(), false);
7785+
const auto & storage_columns = metadata_snapshot->getColumns();
7786+
for (const auto & col_name : subcolumn_names)
7787+
{
7788+
auto column = storage_columns.tryGetColumnOrSubcolumn(GetColumnsOptions::All, col_name);
7789+
if (column && column->isSubcolumn())
7790+
{
7791+
if (auto it = result.find(column->getNameInStorage()); it != result.end())
7792+
result[col_name] = it->second;
7793+
}
7794+
}
7795+
7796+
return result;
7797+
}
7798+
7799+
/// Exact subcolumn sizes are derived per active part from the required substreams.
7800+
/// Snapshot the parts under the lock and release it before the per-part size calculation,
7801+
/// which reads part-local state and would otherwise block part commits and merges.
7802+
DataPartsVector parts;
7803+
{
7804+
auto parts_lock = readLockParts();
7805+
auto committed_parts_range = getDataPartsStateRange(DataPartState::Active);
7806+
parts.assign(committed_parts_range.begin(), committed_parts_range.end());
7807+
}
7808+
7809+
for (const auto & part : parts)
77867810
{
77877811
for (const auto & col_name : subcolumn_names)
77887812
{

src/Storages/MergeTree/MergeTreeData.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1158,7 +1158,7 @@ class MergeTreeData : public WithMutableContext, public IStorage, public IBackgr
11581158
return column_sizes;
11591159
}
11601160

1161-
ColumnSizeByName getColumnSizes(const Names & columns) const override;
1161+
ColumnSizeByName getColumnSizes(const Names & columns, bool calculate_subcolumn_sizes) const override;
11621162

11631163
IndexSizeByName getSecondaryIndexSizes() const override
11641164
{

src/Storages/PostgreSQL/StorageMaterializedPostgreSQL.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -354,10 +354,10 @@ IStorage::ColumnSizeByName StorageMaterializedPostgreSQL::getColumnSizes() const
354354
}
355355

356356

357-
IStorage::ColumnSizeByName StorageMaterializedPostgreSQL::getColumnSizes(const Names & columns) const
357+
IStorage::ColumnSizeByName StorageMaterializedPostgreSQL::getColumnSizes(const Names & columns, bool calculate_subcolumn_sizes) const
358358
{
359359
if (auto nested = tryGetNested())
360-
return nested->getColumnSizes(columns);
360+
return nested->getColumnSizes(columns, calculate_subcolumn_sizes);
361361
return {};
362362
}
363363

src/Storages/PostgreSQL/StorageMaterializedPostgreSQL.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ class StorageMaterializedPostgreSQL final : public IStorage, WithContext
107107
bool supportsOptimizationToSubcolumns() const override;
108108

109109
ColumnSizeByName getColumnSizes() const override;
110-
ColumnSizeByName getColumnSizes(const Names & columns) const override;
110+
ColumnSizeByName getColumnSizes(const Names & columns, bool calculate_subcolumn_sizes) const override;
111111

112112
std::optional<UInt64> totalRows(ContextPtr query_context) const override;
113113
std::optional<UInt64> totalBytes(ContextPtr query_context) const override;

src/Storages/StorageAlias.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ class StorageAlias final : public IStorage, WithContext
270270
}
271271

272272
ColumnSizeByName getColumnSizes() const override { auto target = tryGetTargetTable(); return target ? target->getColumnSizes() : ColumnSizeByName{}; }
273-
ColumnSizeByName getColumnSizes(const Names & columns) const override { auto target = tryGetTargetTable(); return target ? target->getColumnSizes(columns) : ColumnSizeByName{}; }
273+
ColumnSizeByName getColumnSizes(const Names & columns, bool calculate_subcolumn_sizes) const override { auto target = tryGetTargetTable(); return target ? target->getColumnSizes(columns, calculate_subcolumn_sizes) : ColumnSizeByName{}; }
274274
std::optional<ColumnSizeByName> tryGetColumnSizes() const override
275275
{
276276
auto target = tryGetTargetTable();

src/Storages/StorageMerge.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1986,13 +1986,13 @@ IStorage::ColumnSizeByName StorageMerge::getColumnSizes() const
19861986
return column_sizes;
19871987
}
19881988

1989-
IStorage::ColumnSizeByName StorageMerge::getColumnSizes(const Names & columns) const
1989+
IStorage::ColumnSizeByName StorageMerge::getColumnSizes(const Names & columns, bool calculate_subcolumn_sizes) const
19901990
{
19911991
ColumnSizeByName column_sizes;
19921992

19931993
forEachTable([&](const auto & table)
19941994
{
1995-
for (const auto & [name, size] : table->getColumnSizes(columns))
1995+
for (const auto & [name, size] : table->getColumnSizes(columns, calculate_subcolumn_sizes))
19961996
column_sizes[name].add(size);
19971997
});
19981998

src/Storages/StorageMerge.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ class StorageMerge final : public IStorage, WithContext
151151
const IStorage * ignore_self);
152152

153153
ColumnSizeByName getColumnSizes() const override;
154-
ColumnSizeByName getColumnSizes(const Names & columns) const override;
154+
ColumnSizeByName getColumnSizes(const Names & columns, bool calculate_subcolumn_sizes) const override;
155155

156156
std::optional<ColumnSizeByName> tryGetColumnSizes() const override;
157157

0 commit comments

Comments
 (0)