diff --git a/.changeset/lazy-pugs-smoke.md b/.changeset/lazy-pugs-smoke.md new file mode 100644 index 0000000000..0fd3d30296 --- /dev/null +++ b/.changeset/lazy-pugs-smoke.md @@ -0,0 +1,15 @@ +--- +'@hyperdx/common-utils': patch +'@hyperdx/app': patch +--- + +fix: disable per-part subcolumn size calculation on ClickHouse 26.3+ + +ClickHouse 26.3 turned on +`allow_calculating_subcolumns_sizes_for_merge_tree_reading` by default, which +makes PREWHERE planning fetch per-part sizes for every map key a query +references. On SharedMergeTree that is one S3 GET per (key × active part), it +runs before any row is read, and `max_execution_time` does not interrupt it. +Queries referencing many attribute keys — the LLM dashboard reads ~64 — could +spend minutes in planning. Queries now send the setting as `0` when the server +supports it. diff --git a/packages/app/src/llm/dashboard/EfficiencyCharts.tsx b/packages/app/src/llm/dashboard/EfficiencyCharts.tsx index 5a6fad867c..c3bf51c547 100644 --- a/packages/app/src/llm/dashboard/EfficiencyCharts.tsx +++ b/packages/app/src/llm/dashboard/EfficiencyCharts.tsx @@ -23,7 +23,8 @@ const PERCENT_NUMBER_FORMAT: NumberFormat = { */ export function EfficiencyCharts(props: LLMChartProps) { const { source, expressions } = props; - const base = baseLLMChartConfig(props); + // Neither chart selects cost, so skip the ~70 KiB cost alias binding. + const base = baseLLMChartConfig({ ...props, withCostAlias: false }); return ( <> diff --git a/packages/app/src/llm/dashboard/LatencyCharts.tsx b/packages/app/src/llm/dashboard/LatencyCharts.tsx index 7a79509d77..07737db5c6 100644 --- a/packages/app/src/llm/dashboard/LatencyCharts.tsx +++ b/packages/app/src/llm/dashboard/LatencyCharts.tsx @@ -17,7 +17,8 @@ const CHART_HEIGHT = 320; */ export function LatencyCharts(props: LLMChartProps) { const { source, expressions } = props; - const base = baseLLMChartConfig(props); + // Neither chart selects cost, so skip the ~70 KiB cost alias binding. + const base = baseLLMChartConfig({ ...props, withCostAlias: false }); return ( <> diff --git a/packages/common-utils/src/__tests__/clickhouse.test.ts b/packages/common-utils/src/__tests__/clickhouse.test.ts index 14e13606bd..a9b4825660 100644 --- a/packages/common-utils/src/__tests__/clickhouse.test.ts +++ b/packages/common-utils/src/__tests__/clickhouse.test.ts @@ -414,6 +414,10 @@ describe('processClickhouseSettings - optimization settings', () => { // { name: 'use_top_k_dynamic_filtering', value: '1' }, { name: 'use_skip_indexes_on_data_read', value: '1' }, { name: 'use_skip_indexes_for_disjunctions', value: '1' }, + { + name: 'allow_calculating_subcolumns_sizes_for_merge_tree_reading', + value: '1', + }, ]); await client.query({ @@ -440,9 +444,13 @@ describe('processClickhouseSettings - optimization settings', () => { // use_top_k_dynamic_filtering: '1', use_skip_indexes_on_data_read: '1', use_skip_indexes_for_disjunctions: '1', + allow_calculating_subcolumns_sizes_for_merge_tree_reading: '0', }); }); + // The exact-equality assertion below is what keeps unavailable settings off + // the wire — e.g. a pre-26.3 server that would reject + // allow_calculating_subcolumns_sizes_for_merge_tree_reading as unknown. it('should only apply available optimization settings', async () => { setupMockQuery([ { name: 'use_skip_indexes_for_top_k', value: '1' }, diff --git a/packages/common-utils/src/clickhouse/index.ts b/packages/common-utils/src/clickhouse/index.ts index 9df6177583..6a18dc1a2e 100644 --- a/packages/common-utils/src/clickhouse/index.ts +++ b/packages/common-utils/src/clickhouse/index.ts @@ -546,6 +546,15 @@ export abstract class BaseClickhouseClient { // Enables full-text (inverted index) search. applySettingIfAvailable('enable_full_text_index', '1'); + // 26.3 turned this on by default. On SharedMergeTree it makes PREWHERE + // planning fetch per-part sizes for every map key referenced — one S3 GET + // each, not interruptible by max_execution_time. The sizes only reorder + // PREWHERE conditions, so the pre-26.3 approximation is fine. + applySettingIfAvailable( + 'allow_calculating_subcolumns_sizes_for_merge_tree_reading', + '0', + ); + return { ...defaultSettings, ...clickhouse_settings,