快照视图

当前版本:v1.4, 更新时间:2019-10-18

松果时序数据库为每个数据表提供一个快照视图,快照视图包含该表中每个设备最新的一条数据。若某个设备未添加过数据,则不会出现在快照视图中;快照视图名为表名后加".snapshot",例如:表tab01的快照视图为tab01.snapshot快照视图使用实例:

  1. --1. 创建表
  2. CREATE TABLE testSnap
  3. (
  4. devid bigint,
  5. tstamp datetime,
  6. val01 bool,
  7. val02 bigint
  8. )
  9.  
  10. --2. 创建设备
  11. INSERT INTO sys_dev(tabname, devid, devname)
  12. VALUES('testSnap', 1, 'device 1'),
  13. ('testSnap', 2, 'device 2'),
  14. ('testsnap', 3, 'device 3')
  15.  
  16. --3. 插入数据
  17. INSERT INTO testSnap(devid, tstamp, val01, val02)
  18. VALUES(1, now(), true, 101),(2, now(), false, 201)
  19.  
  20. --4. 查询快照
  21. SELECT * FrOM testSnap.snapshot
  22. --结果集
  23. --devid | tstamp | val01 | val02
  24. -- 1 | 2019-10-14 15:37:41 | true | 101
  25. -- 2 | 2019-10-14 15:37:41 | false | 201
  26. --从查询结果可知,设备3未添加过数据,故不会出现在快照视图中
  27.  
  28. --5. 继续插入数据
  29. INSERT INTO testSnap(devid, tstamp, val01, val02)
  30. VALUES(2, now(), true, 202),(3, now(), false, 301)
  31.  
  32. --6. 查询快照
  33. SELECT * FROM testSnap.snapshot
  34. --结果集
  35. --devid | tstamp | val01 | val02
  36. -- 1 | 2019-10-14 15:37:41 | true | 101
  37. -- 2 | 2019-10-14 15:42:27 | true | 202
  38. -- 3 | 2019-10-14 15:42:27 | false | 301
  39. --从查询结果可知,每个设备只有最新的一条数据在快照视图中

下面是利用快照视图提供的一些功能,使用上例中testSnap表:

  • 查询快照中满足某些条件的设备
  1. SELECT *
  2. FROM testSnap.snapshot
  3. WHERE devid in (1, 3, 5) AND val01 = true
  • 以5分钟作为设备离线的标准,即,某设备5分钟之内未上传新数据则认为该设备已离线:
  1. --1. 查询离线设备的总数
  2. SELECT count(*) AS cnt
  3. FROM testSnap.snapshot
  4. WHERE tstamp < now(-5m)
  5.  
  6. --2. 查询离线的设备,前1000
  7. SELECT devid
  8. FROM testSnap.snapshot
  9. WHERE tstamp < now(-5m)
  10. LIMIT 1000

在松果时序数据库中,每次查询最多获取10000条数据,以查询离线设备为例:若要查询的设备超过10000条,则需要多次查询,如果简单使用LIMIT子句查询,两次查询之间可能有一些数据插入会导致某些数据无法查询到。

  1. --1.创建设备
  2. INSERT INTO sys_dev(tabname, devid, devname)
  3. VALUES('testSnap', 101, 'device 101'),
  4. ('testSnap', 102, 'device 102'),
  5. ('testSnap', 103, 'device 103'),
  6. ('testSnap', 104, 'device 104'),
  7. ('testSnap', 105, 'device 105'),
  8. ('testSnap', 106, 'device 106')
  9.  
  10. --2.插入数据,以5分钟离线为例,所有设备都已离线
  11. INSERT INTO testSnap(devid, tstamp, val01, val02)
  12. VALUES(101, now(-10m), true, 1001),
  13. (102, now(-10m), true, 2001),
  14. (103, now(-10m), true, 3001),
  15. (104, now(-10m), true, 4001),
  16. (105, now(-10m), true, 5001),
  17. (106, now(-10m), true, 6001)
  18.  
  19. --3.查询离线数据,每次查询两条
  20. --3.1第一次查询
  21. SELECT * FROM testSnap.snapshot
  22. WHERE tstamp < now(-5m)
  23. LIMIT 0,2
  24. --查询到设备 101,102
  25.  
  26. --3.2第二次查询
  27. SELECT * FROM testSnap.snapshot
  28. WHERE tstamp < now(-5m)
  29. LIMIT 2,2
  30. --查询到设备 103,104
  31.  
  32. --3.3第三次查询
  33. SELECT * FROM testSnap.snapshot
  34. WHERE tstamp < now(-5m)
  35. LIMIT 4,2
  36. --查询到设备 105,106

在上例中,若3.1和3.2之间其他客户端插入了设备101的数据,如下示例:

  1. --3.1第一次查询
  2. SELECT * FROM testSnap.snapshot
  3. WHERE tstamp < now(-5m)
  4. LIMIT 0,2
  5. --查询到设备 101,102
  6.  
  7. --插入数据
  8. INSERT INTO testSnap(devid, tstamp, val01, val02)
  9. VALUES(101, now(), false, 1002)
  10.  
  11. --3.2第二次查询
  12. SELECT * FROM testSnap.snapshot
  13. WHERE tstamp < now(-5m)
  14. LIMIT 2,2
  15. --查询到设备 104,105
  16.  
  17. --3.3第三次查询
  18. SELECT * FROM testSnap.snapshot
  19. WHERE tstamp < now(-5m)
  20. LIMIT 4,2
  21. --查询到设备 106

设备103未被查询到,故:直接使用LIMIT子句多次查询可能会少查询到数据,正确的方式应该如下:

  1. --1. 第一次查询
  2. SELECT * FROM testSnap.snapshot
  3. WHERE tstamp < now(-5m)
  4. LIMIT 2
  5. --查询到设备 101,102
  6.  
  7. --2. 后面的查询
  8. SELECT * FROM testSnap.snapshot
  9. WHERE tstamp < now(-5m) AND devid > 102
  10. LIMIT 2

从第二次开始每次查询限定查询的设备ID大于上一次最大的设备ID,不但能保证查询的数据正确性,还能提高查询性能。