Downsample and compress

Action that downsamples and compresses chunks on hypertable metrics older than a certain age. The example query computes a simple avg over hourly data for downsampling, but this query can be arbitrarily complex.

  1. CREATE OR REPLACE PROCEDURE downsample_compress (job_id int, config jsonb)
  2. LANGUAGE PLPGSQL
  3. AS $$
  4. DECLARE
  5. lag interval;
  6. chunk REGCLASS;
  7. tmp_name name;
  8. BEGIN
  9. SELECT jsonb_object_field_text (config, 'lag')::interval INTO STRICT lag;
  10. IF lag IS NULL THEN
  11. RAISE EXCEPTION 'Config must have lag';
  12. END IF;
  13. FOR chunk IN
  14. SELECT show.oid
  15. FROM show_chunks('metrics', older_than => lag) SHOW (oid)
  16. INNER JOIN pg_class pgc ON pgc.oid = show.oid
  17. INNER JOIN pg_namespace pgns ON pgc.relnamespace = pgns.oid
  18. INNER JOIN timescaledb_information.chunks chunk ON chunk.chunk_name = pgc.relname
  19. AND chunk.chunk_schema = pgns.nspname
  20. WHERE chunk.is_compressed::bool = FALSE
  21. LOOP
  22. RAISE NOTICE 'Processing chunk: %', chunk::text;
  23. -- build name for temp table
  24. SELECT '_tmp' || relname
  25. FROM pg_class
  26. WHERE oid = chunk INTO STRICT tmp_name;
  27. -- copy downsampled chunk data into temp table
  28. EXECUTE format($sql$ CREATE UNLOGGED TABLE %I AS
  29. SELECT time_bucket('1h', time), device_id, avg(value) FROM %s GROUP BY 1, 2;
  30. $sql$, tmp_name, chunk);
  31. -- clear original chunk
  32. EXECUTE format('TRUNCATE %s;', chunk);
  33. -- copy downsampled data back into chunk
  34. EXECUTE format('INSERT INTO %s(time, device_id, value) SELECT * FROM %I;', chunk, tmp_name);
  35. -- drop temp table
  36. EXECUTE format('DROP TABLE %I;', tmp_name);
  37. PERFORM compress_chunk (chunk);
  38. COMMIT;
  39. END LOOP;
  40. END
  41. $$;

Register job to run daily downsampling and compressing chunks older than 12 months.

  1. SELECT add_job('downsample_compress','1d', config => '{"lag":"12 month"}');