разобраться
Есть вот такая таблица:
CREATE TABLE telemetry
(
...
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(timestamp)
PRIMARY KEY (target, schema_path, restconf_path, timestamp)
ORDER BY (target, schema_path, restconf_path, timestamp)
SETTINGS index_granularity = 32768;
и вот такой запрос:
EXPLAIN indexes = 1
SELECT
restconf_path,
toStartOfInterval(timestamp, toIntervalSecond(86400)) AS ts,
MAX(value) AS value,
FROM telemetry
WHERE (target = 'some string')
AND (schema_path LIKE 'some string%')
AND (restconf_path LIKE 'some string%')
AND (ts >= FROM_UNIXTIME(1659916800))
AND (ts <= FROM_UNIXTIME(1661040000))
GROUP BY
restconf_path,
ts
┌─explain─────────────────────────────────────────────────────────────────────────┐
│ Expression ((Projection + Before ORDER BY)) │
│ Aggregating │
│ Expression (Before GROUP BY) │
│ Filter (WHERE) │
│ SettingQuotaAndLimits (Set limits and quota after reading from storage) │
│ ReadFromMergeTree │
│ Indexes: │
│ MinMax │
│ Condition: true │
│ Parts: 39/39 │
│ Granules: 8599636/8599636 │
│ Partition │
│ Condition: true │
│ Parts: 39/39 │
│ Granules: 8599636/8599636 │
│ PrimaryKey │
│ Keys: │
│ target │
│ schema_path │
│ restconf_path │
│ Condition: and((schema_path in ['some string'...), │
│ and(and((restconf_path in ['some string'...)), │
│ (target in ['some string'...])), │
│ (schema_path in ['some string'...)))) │
│ Parts: 33/39 │
│ Granules: 42/8599636 │
└─────────────────────────────────────────────────────────────────────────────────┘
Почему запрос сканит все 8599636 гранул в MinMax и Partition индексах? Как это вылечить?
он не сканит все гранулы, он взял 42 гранулы по primary индексу можете использовать explain estimate, он покажет количество просканированных строк
> Почему запрос сканит все 8599636 гранул в MinMax и Partition индексах? индексов у вас нет, а timestamp (по которому сделано партиционирование) не входит в where. Поэтому осталась только отсечка по первичному индексу > Как это вылечить? А надо? Но если хочется, то можно разобраться чем отличается ts от timestamp и нельзя ли их заменить или в partition by или в where
ts вычисляется с timestamp-a toStartOfInterval(timestamp, toIntervalSecond(86400)) AS ts
ох вот это я не посмотрел 👍 спасибо
так default не гарантирует что ts вычислен из timestamp, вы можете в ts что угодно положить, вам надо просто добавить в partition by PARTITION BY (toYYYYMM(timestamp), toYYYYMM(ts ))
Ts вычисляется в запросе. Partition by в объявлении таблицы. Вы предлагаете добавить materialized поле в таблицу?
Нет. Я предлагаю понять как работает partition pruning.
Я с удовольствием в этом разберусь, но по тем обрывкам информации, что вы выдаете, это будет сложно, к сожалению
Ну у вас партиции по одному полю а фильтруете вы по другому, кх не знает что и там и там одно и тоже https://kb.altinity.com/engines/mergetree-table-engine-family/pick-keys/ https://stackoverflow.com/questions/60142967/how-to-understand-part-and-partition-of-clickhouse?r=SearchResults&s=3%7C56.7987 Т.е.по уму надо оставить одно поле и использовать его и не хранить лишнее, если это невозможно, то можно хакнуть, партиционировать по обеим полям, т.о. чтобы партиция получалась одна, потому что в колонках одна и та же дата.
Почитаю 👍 большое спасибо!
Обсуждают сегодня