我在表中有几百亿行用于4k可变参数,我需要获取其中500个的最后一个值 我的表按天和按参数ID排序,因此我只需要查找具有所需ID的最后一条记录
SELECT max(time)
FROM obj_ntgres.param_values_history
PREWHERE param_id = 4171
工作缓慢: 耗时:0.437秒。已处理256万行,5.21 MB(587万行/秒,11.92 MB /秒)
SELECT *
FROM obj_ntgres.param_values_history
PREWHERE param_id = 4171
ORDER BY time DESC
LIMIT 1
较慢: 设置1行。耗时:3.413秒。已处理256万行,5.45 MB(751.21万行/秒,1.60 MB /秒)
表
CREATE TABLE obj_ntgres.param_values_history (
time DateTime,
param_id UInt16,
param_value Float32,
param_value_quality Decimal(1, 0),
msec Decimal(3, 0)
) ENGINE = MergeTree PARTITION BY toStartOfDay(time)
ORDER BY
param_id SETTINGS index_granularity = 8192
也许您有一些想法使其更快?
我的意思是:在所有表上不使用max()查找最后一个元素
答案 0 :(得分:2)
实际上是它仍然需要使用相同的param_id
扫描大量数据的原因。
几乎没有办法。在开始的所有情况下,都需要向表排序键添加time
列:
CREATE TABLE param_values_history (
time DateTime,
param_id UInt16,
param_value Float32,
param_value_quality Decimal(1, 0),
msec Decimal(3, 0)
) ENGINE = MergeTree PARTITION BY toStartOfDay(time)
ORDER BY
(param_id,time) SETTINGS index_granularity = 8192
此后-如果您的数据是时间对齐的,即,如果您确切地知道所有500个参数在过去的几秒钟/分钟内都有某个值,则只需添加一个类似AND time > now() - INTERVAL 10 MINUTES
的过滤器,它将工作真的非常快(无需扫描很多行)。
如果您的某些参数没有常规活动,则情况会更糟。
在这种情况下,最快的方法是通过实例化视图(甚至是整个最后一行)缓存每个参数的最后时间。像这样:
CREATE MATERIALIZED VIEW last_positions
Engine=ReplacingMergeTree(max_time)
ORDER BY param_id
PARTITION BY tuple()
AS SELECT param_id, max(time) as max_time
FROM param_values_history
GROUP BY param_id;
SELECT * FROM param_values_history PREWHERE (param_id,time) IN (SELECT param_id, max(max_time) FROM last_positions GROUP BY param_id);
或者:MV中收集的最后一行全部
CREATE MATERIALIZED VIEW last_positions
Engine=ReplacingMergeTree(max_time)
ORDER BY param_id
PARTITION BY tuple()
AS SELECT param_id,
argMax(param_value, time) as _param_value,
argMax(param_value_quality, time) as _param_value_quality,
argMax(param_value, msec) as _msec,
max(time) as max_time
FROM param_values_history
GROUP BY param_id;
SELECT * FROM last_positions FINAL;
答案 1 :(得分:0)
我不明白您所说的“工作不好”的意思。但是如果问题是
选择带有特定位置的最后一条记录
您可以尝试一下(根据您的需要进行修改):
SELECT
max((time, param_value, param_value_quality, msec)) AS result,
result.2 AS param_value,
result.3 AS param_value_quality
FROM obj_ntgres.param_values_history
PREWHERE param_id = 4171