时序数据库 TimescaleDB 安装与使用

打印 上一主题 下一主题

主题 681|帖子 681|积分 2047


TimescaleDB 是一个时间序列数据库,建立在 PostgreSQL 之上。然而,不光云云,它照旧时间序列的关系数据库。使用 TimescaleDB 的开发人员将受益于专门构建的时间序列数据库以及经典的关系数据库 (PostgreSQL),所有这些都具有完整的 SQL 支持。本文先容 TimescaleDB 的 CentOS 7 情况源码编译安装与使用。
01 源码安装


安装 TimescaleDB 之前确保你的呆板上已经安装好了 PostgreSQL,而且检查安装的 PG 版本与 TimescaleDB 版本兼容情况:https://docs.timescale.com/self-hosted/latest/upgrades/upgrade-pg/

源码安装必要使用到 CMake 和 GUN 编译器 gcc 等工具,确保呆板已经安装了这些工具
1.1 源码安装 TimescaleDB


  • 拉取 TimescaleDB 源码
  1. git clone https://github.com/timescale/timescaledb
复制代码

  • 进入源码目录并切换分支到指定版本
  1. cd timescaledb
  2. git checkout 2.11.1
复制代码

  • 实行 bootstrap 引导构建体系
  1. ./bootstrap
复制代码
  碰到报错:PostgreSQL was built without OpenSSL support, which TimescaleDB needs for full compatibility
解决方法:重新编译安装 postgresql,增长 --with-openssl 选项
./configure --prefix=/home/randy/soft/postgresql --with-openssl
或者实行 ./bootstrap
-DUSE_OPENSSL=0 不使用 openssl

  

  • 进入上一步生成的 build 目录,编译安装 timescaledb
  1. cd build
  2. make && make install
复制代码
安装完成之后,就可以在 postgresql 插件目录下看到 timescaledb 了

1.2 修改 PG 设置

完成 TimescaleDB 安装之后,必要修改 postgresql 设置文件增长 timescaledb 预加载库

  • 找到 pg 设置文件
  1. $ psql -Upostgres -dpostgres -c "SHOW config_file;"
  2. Password for user postgres:
  3.                    config_file
  4. --------------------------------------------------
  5. /home/randy/soft/postgresql/data/postgresql.conf
  6. (1 row)
复制代码

  • 修改 pg 设置文件
  1. vim /home/randy/soft/postgresql/data/postgresql.conf
  2. # 做如下修改
  3. shared_preload_libraries = 'timescaledb'
复制代码
修改完成之后重启 pg
1.3 安装 TimescaleDB 插件


  • 实行如下下令创建 timescaledb 插件
  1. CREATE EXTENSION IF NOT EXISTS timescaledb;
复制代码

  • 完成插件创建之后可以使用 \dx 下令查看插件是否成功安装
  1. testdb=# \dx
  2.                                                 List of installed extensions
  3.     Name     | Version |   Schema   |                                      Description
  4. -------------+---------+------------+---------------------------------------------------------------------------------------
  5. plpgsql     | 1.0     | pg_catalog | PL/pgSQL procedural language
  6. timescaledb | 2.11.1  | public     | Enables scalable inserts and complex queries for time-series data (Community Edition)
  7. (2 rows)
复制代码

至此,postgresql + timescaledb 时序数据库就安装完成了

  • 不想再用这个插件的话,使用如下下令删除插件
  1. DROP EXTENSION IF EXISTS timescaledb;
复制代码
02 Timescale 基础使用


2.1 创建超表 hypertables


  • CREATE 创建一个 pg 普通表
  1. testdb=# CREATE TABLE conditions (
  2.   time        TIMESTAMPTZ       NOT NULL,
  3.   location    TEXT              NOT NULL,
  4.   device      TEXT              NOT NULL,
  5.   temperature DOUBLE PRECISION  NULL,
  6.   humidity    DOUBLE PRECISION  NULL
  7. );
  8. CREATE TABLE
复制代码
然后使用 create_hypertable 函数将普通表转化成 hypertable
  1. testdb=# SELECT create_hypertable('conditions', 'time');
  2.     create_hypertable
  3. -------------------------
  4. (1,public,conditions,t)
  5. (1 row)
复制代码

  • INSERT 向 hypertable 中插入数据
  1. testdb=# INSERT INTO conditions(time, location, device, temperature, humidity)
  2. SELECT now(), to_char(i, 'FM0000'), to_char(i, 'FM00000'), random()*i, random()*i FROM generate_series(1,10000) i;
  3. INSERT 0 10000
复制代码

  • SELECT 查询 hypertable 数据
  1. testdb=# SELECT * FROM conditions ORDER BY time DESC LIMIT 10;
  2.              time              | location | device |     temperature     |       humidity
  3. -------------------------------+----------+--------+---------------------+----------------------
  4. 2023-08-03 12:37:00.345665+08 | 0001     | 00001  | 0.24349980974765373 |   0.5948687729797264
  5. 2023-08-03 12:37:00.345665+08 | 0002     | 00002  |  1.8149739913052656 |    0.616265502369167
  6. 2023-08-03 12:37:00.345665+08 | 0003     | 00003  |   2.400422475569293 |   0.6870057094407791
  7. 2023-08-03 12:37:00.345665+08 | 0004     | 00004  |   2.639553072461581 |   1.9409034849705193
  8. 2023-08-03 12:37:00.345665+08 | 0005     | 00005  |   2.127623537273031 |   3.8871503537982655
  9. 2023-08-03 12:37:00.345665+08 | 0006     | 00006  |  2.3469833801156312 |    4.411529933527426
  10. 2023-08-03 12:37:00.345665+08 | 0007     | 00007  |  1.0073460031664823 | 0.016827997740616496
  11. 2023-08-03 12:37:00.345665+08 | 0008     | 00008  |   7.023014897212306 |   0.8679293544022073
  12. 2023-08-03 12:37:00.345665+08 | 0009     | 00009  |   6.744935559863428 |    6.312948981297968
  13. 2023-08-03 12:37:00.345665+08 | 0010     | 00010  |   9.279208258323166 |    9.451548543523778
  14. (10 rows)
复制代码

  • UPDATE 更新 hypertable 数据
更新数据的语句与标准 SQL 一致,如下示例修改指定记载的值
  1. testdb=# SELECT * FROM conditions
  2. WHERE time = '2023-08-03 12:37:00.345665+08' AND location = '0001';
  3.              time              | location | device |     temperature     |      humidity
  4. -------------------------------+----------+--------+---------------------+--------------------
  5. 2023-08-03 12:37:00.345665+08 | 0001     | 00001  | 0.24349980974765373 | 0.5948687729797264
  6. (1 row)
  7. testdb=# UPDATE conditions SET temperature = 70.2, humidity = 50.0
  8. WHERE time = '2023-08-03 12:37:00.345665+08' AND location = '0001';
  9. UPDATE 1
  10. testdb=# SELECT * FROM conditions
  11. WHERE time = '2023-08-03 12:37:00.345665+08' AND location = '0001';
  12.              time              | location | device | temperature | humidity
  13. -------------------------------+----------+--------+-------------+----------
  14. 2023-08-03 12:37:00.345665+08 | 0001     | 00001  |        70.2 |       50
  15. (1 row)
复制代码
也可以修改该指定范围内的多行记载,如下例子中修改时间 2023-08-03 12:37:00 到 2023-08-03 12:37:05 这 5 秒内的数据如下
  1. testdb=# SELECT * FROM conditions ORDER BY time DESC LIMIT 10;
  2.              time              | location | device |    temperature     |       humidity
  3. -------------------------------+----------+--------+--------------------+----------------------
  4. 2023-08-03 12:37:00.345665+08 | 0002     | 00002  | 1.8149739913052656 |    0.616265502369167
  5. 2023-08-03 12:37:00.345665+08 | 0003     | 00003  |  2.400422475569293 |   0.6870057094407791
  6. 2023-08-03 12:37:00.345665+08 | 0004     | 00004  |  2.639553072461581 |   1.9409034849705193
  7. 2023-08-03 12:37:00.345665+08 | 0005     | 00005  |  2.127623537273031 |   3.8871503537982655
  8. 2023-08-03 12:37:00.345665+08 | 0006     | 00006  | 2.3469833801156312 |    4.411529933527426
  9. 2023-08-03 12:37:00.345665+08 | 0007     | 00007  | 1.0073460031664823 | 0.016827997740616496
  10. 2023-08-03 12:37:00.345665+08 | 0008     | 00008  |  7.023014897212306 |   0.8679293544022073
  11. 2023-08-03 12:37:00.345665+08 | 0009     | 00009  |  6.744935559863428 |    6.312948981297968
  12. 2023-08-03 12:37:00.345665+08 | 0010     | 00010  |  9.279208258323166 |    9.451548543523778
  13. 2023-08-03 12:37:00.345665+08 | 0011     | 00011  |  1.994685462372594 |    7.361677356344085
  14. (10 rows)
  15. testdb=# UPDATE conditions SET temperature = temperature + 0.1
  16. WHERE time >= '2023-08-03 12:37:00' AND time < '2023-08-03 12:37:05';
  17. UPDATE 10000
  18. testdb=# SELECT * FROM conditions ORDER BY time DESC LIMIT 10;
  19.              time              | location | device |    temperature     |       humidity
  20. -------------------------------+----------+--------+--------------------+----------------------
  21. 2023-08-03 12:37:00.345665+08 | 0002     | 00002  | 1.9149739913052657 |    0.616265502369167
  22. 2023-08-03 12:37:00.345665+08 | 0003     | 00003  |  2.500422475569293 |   0.6870057094407791
  23. 2023-08-03 12:37:00.345665+08 | 0004     | 00004  |  2.739553072461581 |   1.9409034849705193
  24. 2023-08-03 12:37:00.345665+08 | 0005     | 00005  | 2.2276235372730313 |   3.8871503537982655
  25. 2023-08-03 12:37:00.345665+08 | 0006     | 00006  | 2.4469833801156313 |    4.411529933527426
  26. 2023-08-03 12:37:00.345665+08 | 0007     | 00007  | 1.1073460031664824 | 0.016827997740616496
  27. 2023-08-03 12:37:00.345665+08 | 0008     | 00008  |  7.123014897212306 |   0.8679293544022073
  28. 2023-08-03 12:37:00.345665+08 | 0009     | 00009  |  6.844935559863428 |    6.312948981297968
  29. 2023-08-03 12:37:00.345665+08 | 0010     | 00010  |  9.379208258323166 |    9.451548543523778
  30. 2023-08-03 12:37:00.345665+08 | 0011     | 00011  |  2.094685462372594 |    7.361677356344085
  31. (10 rows)
复制代码

  • Upsert 插入新数据或更新已存在的数据
Upsert 只能在存在唯一索引或唯一约束的表中收效,可以使用 ALTER TABLE … ADD CONSTRAINT … UNIQUE 语句为已经存在的 hypertable 创建唯一约束
  1. testdb=# ALTER TABLE conditions
  2.   ADD CONSTRAINT conditions_time_location
  3.     UNIQUE (time, location);
  4. ALTER TABLE
  5. testdb=# \d conditions
  6.                         Table "public.conditions"
  7.    Column    |           Type           | Collation | Nullable | Default
  8. -------------+--------------------------+-----------+----------+---------
  9. time        | timestamp with time zone |           | not null |
  10. location    | text                     |           | not null |
  11. device      | text                     |           | not null |
  12. temperature | double precision         |           |          |
  13. humidity    | double precision         |           |          |
  14. Indexes:
  15.     "conditions_time_location" UNIQUE CONSTRAINT, btree ("time", location)
  16.     "conditions_time_idx" btree ("time")
  17. Triggers:
  18.     ts_insert_blocker BEFORE INSERT ON conditions FOR EACH ROW EXECUTE FUNCTION _timescaledb_internal.insert_blocker()
  19. Number of child tables: 1 (Use \d+ to list them.)
复制代码
插入新数据或更新已存在的数据使用 INSERT INTO … VALUES … ON CONFLICT … DO UPDATE 语句实现
  1. testdb=# SELECT * FROM conditions
  2. WHERE time = '2023-08-03 12:37:00.345665+08' AND location = '0001';
  3.              time              | location | device | temperature | humidity
  4. -------------------------------+----------+--------+-------------+----------
  5. 2023-08-03 12:37:00.345665+08 | 0001     | 00001  |        70.3 |       50
  6. (1 row)
  7. testdb=# INSERT INTO conditions
  8. VALUES ('2023-08-03 12:37:00.345665+08', '0001', '00001', 70.2, 50.1)
  9. ON CONFLICT (time, location) DO UPDATE
  10.   SET temperature = excluded.temperature,
  11.         humidity = excluded.humidity;
  12. INSERT 0 1
  13. testdb=# SELECT * FROM conditions
  14. WHERE time = '2023-08-03 12:37:00.345665+08' AND location = '0001';
  15.              time              | location | device | temperature | humidity
  16. -------------------------------+----------+--------+-------------+----------
  17. 2023-08-03 12:37:00.345665+08 | 0001     | 00001  |        70.2 |     50.1
  18. (1 row)
复制代码
也可以只实行插入操作,如果记载已存在则直接跳过,该操作使用 INSERT INTO … VALUES … ON CONFLICT DO NOTHING 语句实现
  1. testdb=# INSERT INTO conditions
  2.   VALUES (NOW(), 'new', '00001', 70.1, 50.0)
  3.   ON CONFLICT DO NOTHING;
  4. INSERT 0 1
  5. testdb=# SELECT * FROM conditions WHERE location = 'new';
  6.              time              | location | device | temperature | humidity
  7. -------------------------------+----------+--------+-------------+----------
  8. 2023-08-04 10:33:16.698018+08 | new      | 00001  |        70.1 |       50
  9. (1 row)
  10. testdb=# INSERT INTO conditions
  11. VALUES ('2023-08-04 10:33:16.698018+08', '0001', '00001', 71, 50.1)
  12. ON CONFLICT DO NOTHING;
  13. INSERT 0 1
  14. testdb=# SELECT * FROM conditions WHERE location = 'new';
  15.              time              | location | device | temperature | humidity
  16. -------------------------------+----------+--------+-------------+----------
  17. 2023-08-04 10:33:16.698018+08 | new      | 00001  |        70.1 |       50
  18. (1 row)
复制代码

  • DELETE 删除数据
删除数据的语句与标准 SQL 一致 DELETE FROM …
  1. testdb=# SELECT * FROM conditions WHERE location = 'new';
  2.              time              | location | device | temperature | humidity
  3. -------------------------------+----------+--------+-------------+----------
  4. 2023-08-04 10:33:16.698018+08 | new      | 00001  |        70.1 |       50
  5. (1 row)
  6. testdb=# DELETE FROM conditions WHERE location = 'new';
  7. DELETE 1
  8. testdb=# SELECT * FROM conditions WHERE location = 'new';
  9. time | location | device | temperature | humidity
  10. ------+----------+--------+-------------+----------
  11. (0 rows)
复制代码

  • DROP 删除 hypertable 只必要使用 PG 下令删除基表(普通表)即可
  1. testdb=# DROP TABLE conditions;
  2. DROP TABLE
复制代码
2.2 编辑超表 hypertable

hypertable 的修改和标准 SQL 一致,可以使用 ALTER TABLE 相关语句实现:http://www.postgres.cn/docs/12/ddl-alter.html

  • 增删列
增长列 column 时,如果没有默认值即 NULL 时,新增操作可以很快完成;但是默认值为非空的时候,就必要花大量时间填充所有分区中每条记载新增列的值。
别的,无法对已经被压缩的 hypertable 进行增删列操作,如果要进行该操作必要先解压
  1. testdb=# \d conditions
  2.                         Table "public.conditions"
  3.    Column    |           Type           | Collation | Nullable | Default
  4. -------------+--------------------------+-----------+----------+---------
  5. time        | timestamp with time zone |           | not null |
  6. location    | text                     |           | not null |
  7. device      | text                     |           | not null |
  8. temperature | double precision         |           |          |
  9. humidity    | double precision         |           |          |
  10. Indexes:
  11.     "conditions_time_idx" btree ("time" DESC)
  12. Triggers:
  13.     ts_insert_blocker BEFORE INSERT ON conditions FOR EACH ROW EXECUTE FUNCTION _timescaledb_internal.insert_blocker()
  14. Number of child tables: 1 (Use \d+ to list them.)
  15. testdb=# ALTER TABLE conditions
  16. ADD COLUMN test_column DOUBLE PRECISION NULL;
  17. ALTER TABLE
  18. testdb=# \d conditions
  19.                         Table "public.conditions"
  20.    Column    |           Type           | Collation | Nullable | Default
  21. -------------+--------------------------+-----------+----------+---------
  22. time        | timestamp with time zone |           | not null |
  23. location    | text                     |           | not null |
  24. device      | text                     |           | not null |
  25. temperature | double precision         |           |          |
  26. humidity    | double precision         |           |          |
  27. test_column | double precision         |           |          |
  28. Indexes:
  29.     "conditions_time_idx" btree ("time" DESC)
  30. Triggers:
  31.     ts_insert_blocker BEFORE INSERT ON conditions FOR EACH ROW EXECUTE FUNCTION _timescaledb_internal.insert_blocker()
  32. Number of child tables: 1 (Use \d+ to list them.)
  33. testdb=# ALTER TABLE conditions
  34. DROP COLUMN test_column;
  35. ALTER TABLE
  36. testdb=# \d conditions
  37.                         Table "public.conditions"
  38.    Column    |           Type           | Collation | Nullable | Default
  39. -------------+--------------------------+-----------+----------+---------
  40. time        | timestamp with time zone |           | not null |
  41. location    | text                     |           | not null |
  42. device      | text                     |           | not null |
  43. temperature | double precision         |           |          |
  44. humidity    | double precision         |           |          |
  45. Indexes:
  46.     "conditions_time_idx" btree ("time" DESC)
  47. Triggers:
  48.     ts_insert_blocker BEFORE INSERT ON conditions FOR EACH ROW EXECUTE FUNCTION _timescaledb_internal.insert_blocker()
  49. Number of child tables: 1 (Use \d+ to list them.)
复制代码

  • 重命名列或表
  1. testdb=# \d conditions
  2.                         Table "public.conditions"
  3.    Column    |           Type           | Collation | Nullable | Default
  4. -------------+--------------------------+-----------+----------+---------
  5. time        | timestamp with time zone |           | not null |
  6. location    | text                     |           | not null |
  7. device      | text                     |           | not null |
  8. temperature | double precision         |           |          |
  9. humidity    | double precision         |           |          |
  10. test_column | double precision         |           |          |
  11. Indexes:
  12.     "conditions_time_idx" btree ("time" DESC)
  13. Triggers:
  14.     ts_insert_blocker BEFORE INSERT ON conditions FOR EACH ROW EXECUTE FUNCTION _timescaledb_internal.insert_blocker()
  15. Number of child tables: 1 (Use \d+ to list them.)
  16. testdb=# ALTER TABLE conditions RENAME COLUMN test_column TO ts_column;
  17. ALTER TABLE
  18. testdb=# ALTER TABLE conditions RENAME TO weather;
  19. ALTER TABLE
  20. testdb=# \d conditions
  21. Did not find any relation named "conditions".
  22. testdb=# \d weather
  23.                          Table "public.weather"
  24.    Column    |           Type           | Collation | Nullable | Default
  25. -------------+--------------------------+-----------+----------+---------
  26. time        | timestamp with time zone |           | not null |
  27. location    | text                     |           | not null |
  28. device      | text                     |           | not null |
  29. temperature | double precision         |           |          |
  30. humidity    | double precision         |           |          |
  31. ts_column   | double precision         |           |          |
  32. Indexes:
  33.     "conditions_time_idx" btree ("time" DESC)
  34. Triggers:
  35.     ts_insert_blocker BEFORE INSERT ON weather FOR EACH ROW EXECUTE FUNCTION _timescaledb_internal.insert_blocker()
  36. Number of child tables: 1 (Use \d+ to list them.)
复制代码
2.3 修改 hypertable 分区间隔


  • 普通表转化成 hypertable 时指定分区时间间隔 chunk_time_interval
如果创建 hypertable 是没有指定分区间隔,默认值是 7 天;可以通过查询 _timescaledb.catalog 查看分区间隔的当前设置
  1. testdb=# CREATE TABLE conditions (
  2.   time        TIMESTAMPTZ       NOT NULL,
  3.   location    TEXT              NOT NULL,
  4.   device      TEXT              NOT NULL,
  5.   temperature DOUBLE PRECISION  NULL,
  6.   humidity    DOUBLE PRECISION  NULL
  7. );
  8. CREATE TABLE
  9. testdb=# SELECT create_hypertable('conditions', 'time');    create_hypertable------------------------- (2,public,conditions,t)(1 row)testdb=# SELECT h.table_name, c.interval_length  FROM _timescaledb_catalog.dimension c  JOIN _timescaledb_catalog.hypertable h    ON h.id = c.hypertable_id; table_name | interval_length------------+----------------- conditions |    604800000000(1 row)
复制代码
可以看到没有指定 chunk_time_interval 的 hypertable 分区间隔为 604800000000 / 1000 / 1000 / 60 / 60 / 24 = 7,interval_length 的单位为微秒(microsecond)
创建 hypertable 时我们通过 chunk_time_interval 指定分区间隔为 1 天
  1. testdb=# DROP TABLE conditions;
  2. DROP TABLE
  3. testdb=# CREATE TABLE conditions (
  4.   time        TIMESTAMPTZ       NOT NULL,
  5.   location    TEXT              NOT NULL,
  6.   device      TEXT              NOT NULL,
  7.   temperature DOUBLE PRECISION  NULL,
  8.   humidity    DOUBLE PRECISION  NULL
  9. );
  10. CREATE TABLE
  11. testdb=# SELECT create_hypertable(  'conditions',  'time',  chunk_time_interval => INTERVAL '1 day');    create_hypertable------------------------- (3,public,conditions,t)(1 row)testdb=# SELECT h.table_name, c.interval_length  FROM _timescaledb_catalog.dimension c  JOIN _timescaledb_catalog.hypertable h    ON h.id = c.hypertable_id; table_name | interval_length------------+----------------- conditions |     86400000000(1 row)
复制代码

  • 通过 set_chunk_time_interval 函数修改 hypertable 分区间隔
必要注意的是修改分区时间间隔只会再新建的分区中收效,已经创建的分区不会受到影响。所以如果创建了一个很长时间的分区间隔例如 1 年,然后你想修改成一个更小的分区间隔,那这个更小间隔只会在一年后收效了,这时候只能新建一个表设置分区间隔,然后迁徙数据了。
  1. testdb=# SELECT set_chunk_time_interval('conditions', INTERVAL '12 hours');
  2. set_chunk_time_interval
  3. -------------------------
  4. (1 row)
  5. testdb=# SELECT h.table_name, c.interval_length
  6.   FROM _timescaledb_catalog.dimension c
  7.   JOIN _timescaledb_catalog.hypertable h
  8.     ON h.id = c.hypertable_id;
  9. table_name | interval_length
  10. ------------+-----------------
  11. conditions |     43200000000
  12. (1 row)
复制代码
2.4 hypertable 创建索引

在一个 hypertable 中创建索引分为两步:
   

  • 确定该超表的分区列有哪些,其中 time 列是所有 hypertable 表的分区列,所以创建索引必须包罗该列;别的,在创建 hypertable 表时可以通过 partitioning_column 字段指定空间分区列。
  • 创建的索引组合必须包括所有分区列,在此基础上增长其他列
  

  • 创建索引
hypertable 中索引的创建还是使用标准的 SQL 语句 CREATE INDEX / CREATE UNIQUE INDEX,例如,如下例子中在 conditions 超表的 time 和 device 列上建立索引 idx_device_time
  1. testdb=# \d conditions
  2.                         Table "public.conditions"
  3.    Column    |           Type           | Collation | Nullable | Default
  4. -------------+--------------------------+-----------+----------+---------
  5. time        | timestamp with time zone |           | not null |
  6. location    | text                     |           | not null |
  7. device      | text                     |           | not null |
  8. temperature | double precision         |           |          |
  9. humidity    | double precision         |           |          |
  10. Indexes:
  11.     "conditions_time_idx" btree ("time" DESC)
  12. Triggers:
  13.     ts_insert_blocker BEFORE INSERT ON conditions FOR EACH ROW EXECUTE FUNCTION _timescaledb_internal.insert_blocker()
  14. Number of child tables: 1 (Use \d+ to list them.)
  15. testdb=# CREATE UNIQUE INDEX idx_device_time
  16. ON conditions(device, time);
  17. CREATE INDEX
  18. testdb=# \d conditions
  19.                         Table "public.conditions"
  20.    Column    |           Type           | Collation | Nullable | Default
  21. -------------+--------------------------+-----------+----------+---------
  22. time        | timestamp with time zone |           | not null |
  23. location    | text                     |           | not null |
  24. device      | text                     |           | not null |
  25. temperature | double precision         |           |          |
  26. humidity    | double precision         |           |          |
  27. Indexes:
  28.     "idx_device_time" UNIQUE, btree (device, "time")
  29.     "conditions_time_idx" btree ("time" DESC)
  30. Triggers:
  31.     ts_insert_blocker BEFORE INSERT ON conditions FOR EACH ROW EXECUTE FUNCTION _timescaledb_internal.insert_blocker()
  32. Number of child tables: 1 (Use \d+ to list them.)
复制代码
idx_device_time 索引中包罗了所有分区列 time,而 device 不是分区列,如果创建的索引组合不包罗分区列,会抛出错误,如下 idx_device 索引仅建立在 device 列上
  1. testdb=# CREATE UNIQUE INDEX idx_device
  2. ON conditions(device);
  3. ERROR:  cannot create a unique index without the column "time" (used in partitioning)
  4. testdb=#
复制代码

  • 删除索引
hypertable 中删除索引还是使用标准的 SQL 语句 DROP INDEX,删除 conditions 超表中的索引 idx_device_time
必要注意的是DBMS为主键约束和唯一约束主动创建的索引是无法删除的
  1. testdb=# \d conditions
  2.                         Table "public.conditions"
  3.    Column    |           Type           | Collation | Nullable | Default
  4. -------------+--------------------------+-----------+----------+---------
  5. time        | timestamp with time zone |           | not null |
  6. location    | text                     |           | not null |
  7. device      | text                     |           | not null |
  8. temperature | double precision         |           |          |
  9. humidity    | double precision         |           |          |
  10. Indexes:
  11.     "idx_device_time" UNIQUE, btree (device, "time")
  12.     "conditions_time_idx" btree ("time" DESC)
  13. Triggers:
  14.     ts_insert_blocker BEFORE INSERT ON conditions FOR EACH ROW EXECUTE FUNCTION _timescaledb_internal.insert_blocker()
  15. Number of child tables: 1 (Use \d+ to list them.)
  16. testdb=# DROP INDEX idx_device_time;
  17. DROP INDEX
  18. testdb=# \d conditions
  19.                         Table "public.conditions"
  20.    Column    |           Type           | Collation | Nullable | Default
  21. -------------+--------------------------+-----------+----------+---------
  22. time        | timestamp with time zone |           | not null |
  23. location    | text                     |           | not null |
  24. device      | text                     |           | not null |
  25. temperature | double precision         |           |          |
  26. humidity    | double precision         |           |          |
  27. Indexes:
  28.     "conditions_time_idx" btree ("time" DESC)
  29. Triggers:
  30.     ts_insert_blocker BEFORE INSERT ON conditions FOR EACH ROW EXECUTE FUNCTION _timescaledb_internal.insert_blocker()
  31. Number of child tables: 1 (Use \d+ to list them.)
复制代码

  • 已建索引的普通表转化为 hypertable,空间分区列 partitioning_column 必须包罗在已建的索引中
例如,我们在普通表 basic_table 中已经在 device_id 和 time 列上建立了索引 idx_deviceid_time,那么创建以该表为基表的 hypertable 的分区列必要包罗在索引列中,即分区列仅能为 time 与 device_id 的组合。
下例中,将已经创建好索引的 basic_table 表转化为仅以 time 为分区列的 hypertable
  1. testdb=# CREATE TABLE basic_table(
  2.   time TIMESTAMPTZ,
  3.   user_id BIGINT,
  4.   device_id BIGINT,
  5.   value FLOAT
  6. );
  7. CREATE TABLE
  8. testdb=# CREATE UNIQUE INDEX idx_deviceid_time
  9.   ON basic_table(device_id, time);
  10. CREATE INDEX
  11. testdb=# \d basic_table
  12.                       Table "public.basic_table"
  13.   Column   |           Type           | Collation | Nullable | Default
  14. -----------+--------------------------+-----------+----------+---------
  15. time      | timestamp with time zone |           |          |
  16. user_id   | bigint                   |           |          |
  17. device_id | bigint                   |           |          |
  18. value     | double precision         |           |          |
  19. Indexes:
  20.     "idx_deviceid_time" UNIQUE, btree (device_id, "time")
  21. testdb=# SELECT * from create_hypertable('basic_table', 'time');
  22. NOTICE:  adding not-null constraint to column "time"
  23. DETAIL:  Time dimensions cannot have NULL values.
  24. hypertable_id | schema_name | table_name  | created
  25. ---------------+-------------+-------------+---------
  26.              4 | public      | basic_table | t
  27. (1 row)
  28. testdb=# \d basic_table
  29.                       Table "public.basic_table"
  30.   Column   |           Type           | Collation | Nullable | Default
  31. -----------+--------------------------+-----------+----------+---------
  32. time      | timestamp with time zone |           | not null |
  33. user_id   | bigint                   |           |          |
  34. device_id | bigint                   |           |          |
  35. value     | double precision         |           |          |
  36. Indexes:
  37.     "idx_deviceid_time" UNIQUE, btree (device_id, "time")
  38.     "basic_table_time_idx" btree ("time" DESC)
  39. Triggers:
  40.     ts_insert_blocker BEFORE INSERT ON basic_table FOR EACH ROW EXECUTE FUNCTION _timescaledb_internal.insert_blocker()
复制代码
也可以将已经创建好索引的 basic_table 表转化为以 time 和 device_id 为分区列的 hypertable
  1. testdb=# SELECT * FROM create_hypertable(
  2.   'basic_table',
  3.   'time',
  4.   partitioning_column => 'device_id',
  5.   number_partitions => 4
  6. );
  7. NOTICE:  adding not-null constraint to column "time"
  8. DETAIL:  Time dimensions cannot have NULL values.
  9. hypertable_id | schema_name | table_name  | created
  10. ---------------+-------------+-------------+---------
  11.              5 | public      | basic_table | t
  12. (1 row)
  13. testdb=# \d basic_table
  14.                       Table "public.basic_table"
  15.   Column   |           Type           | Collation | Nullable | Default
  16. -----------+--------------------------+-----------+----------+---------
  17. time      | timestamp with time zone |           | not null |
  18. user_id   | bigint                   |           |          |
  19. device_id | bigint                   |           |          |
  20. value     | double precision         |           |          |
  21. Indexes:
  22.     "idx_deviceid_time" UNIQUE, btree (device_id, "time")
  23.     "basic_table_time_idx" btree ("time" DESC)
  24. Triggers:
  25.     ts_insert_blocker BEFORE INSERT ON basic_table FOR EACH ROW EXECUTE FUNCTION _timescaledb_internal.insert_blocker()
复制代码
但是,我们无法将不在索引组合中的 user_id 作为创建 hypertable 时的分区列
要解决这个问题,要确保在转化为超表之前建立的所有索引都要包罗 hypertable 的分区列,所以将已存在的索引中参加 user_id 即可(重建索引可以重建一个索引,然后删除老的索引,避免使用 reindex 重建索引,因为该过程是壅闭的,一样平常大表不建议使用这个下令 )
  1. testdb=# \d basic_table
  2.                       Table "public.basic_table"
  3.   Column   |           Type           | Collation | Nullable | Default
  4. -----------+--------------------------+-----------+----------+---------
  5. time      | timestamp with time zone |           |          |
  6. user_id   | bigint                   |           |          |
  7. device_id | bigint                   |           |          |
  8. value     | double precision         |           |          |
  9. Indexes:
  10.     "idx_deviceid_time" UNIQUE, btree (device_id, "time")
  11. testdb=# SELECT * FROM create_hypertable(
  12.   'basic_table',
  13.   'time',
  14.   partitioning_column => 'user_id',
  15.   number_partitions => 4
  16. );
  17. NOTICE:  adding not-null constraint to column "time"
  18. DETAIL:  Time dimensions cannot have NULL values.
  19. ERROR:  cannot create a unique index without the column "user_id" (used in partitioning)
  20. testdb=# DROP INDEX idx_deviceid_time;
  21. DROP INDEX
  22. testdb=# CREATE UNIQUE INDEX idx_userid_deviceid_time
  23.   ON basic_table(user_id, device_id, time);
  24. CREATE INDEX
  25. testdb=# \d basic_table
  26.                       Table "public.basic_table"
  27.   Column   |           Type           | Collation | Nullable | Default
  28. -----------+--------------------------+-----------+----------+---------
  29. time      | timestamp with time zone |           |          |
  30. user_id   | bigint                   |           |          |
  31. device_id | bigint                   |           |          |
  32. value     | double precision         |           |          |
  33. Indexes:
  34.     "idx_userid_deviceid_time" UNIQUE, btree (user_id, device_id, "time")
  35. testdb=# SELECT * FROM create_hypertable(
  36.   'basic_table',
  37.   'time',
  38.   partitioning_column => 'user_id',
  39.   number_partitions => 4
  40. );
  41. NOTICE:  adding not-null constraint to column "time"
  42. DETAIL:  Time dimensions cannot have NULL values.
  43. hypertable_id | schema_name | table_name  | created
  44. ---------------+-------------+-------------+---------
  45.             12 | public      | basic_table | t
  46. (1 row)
复制代码

如果文章对你有资助,欢迎一键三连

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

王國慶

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表