Ganos实时热力聚合查询能力解析与最佳实践

本文涉及的产品
云原生数据库 PolarDB MySQL 版,通用型 2核4GB 50GB
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: Ganos是由阿里云数据库产品事业部与飞天实验室共同研发的新一代云原生位置智能引擎,集成于PolarDB-PG、Lindorm、AnalyticDB-PG和RDS-PG等核心产品中。Ganos拥有十大核心引擎,涵盖几何、栅格、轨迹等多种数据处理能力,实现了多模多态数据的一体化存储、查询与分析。本文重点介绍了Ganos的热力瓦片(HMT)技术,通过实时热力聚合查询与动态输出热力瓦片,无需预处理即可实现大规模数据秒级聚合与渲染,适用于交通、城市管理、共享出行等多个领域。HMT相比传统网格聚合技术具有高效、易用的优势,并已在多个真实场景中验证其卓越性能。

关于Ganos
Ganos是阿里云数据库产品事业部联合飞天数据库与存储实验室共同研发的新一代云原生位置智能引擎,它将时空数据处理能力融入了云原生关系型数据库PolarDB-PG、云原生多模数据库Lindorm、云原生数据仓库AnalyticDB-PG和云数据库RDS-PG等核心产品中。Ganos目前拥有几何、栅格、轨迹、表面网格、体网格、3D实景、点云、路径、地理网格、快显十大核心引擎,为数据库构建了面向新型物理世界多模多态数据的存储、查询、分析、服务等一体化能力。
本文主要介绍Ganos实时热力聚合查询并动态输出热力瓦片能力,依托阿里云PolarDB PostgreSQL产品、ADB PostgreSQL和RDS PostgreSQL 三款数据库建设输出。

  1. 关于热力瓦片
    2.1 什么是热力瓦片
    热力瓦片(HeatMap Tile,简称HMT)底层基于Ganos首创的大规模矢量/轨迹数据实时热力聚合查询技术,用于将查询处理结果即时返回client的数据交换结构,它改变了热力统计分析中“聚合需要预打码、展示需要预切片”的传统方式,可针对百万级、千万级、亿级规模数据秒级聚合并渲染。HMT支持多种常用聚合函数与代数表达式,客户可选择统计业务关心的指标并随地图的放大缩小进行不同层级的动态计算和实时绘制,极大程度提升了业务效率,为客户产品带来的更多可能。在本年度的云栖大会上,Ganos发布了这项能力,并现场展示了基于HMT构建大规模运输轨迹实时查询聚合的案例,帮助客户把以往需要线下预处理才能发布的数据产品完全在线化,该功能得到了很大行业反响与认可。
    2.2 热力瓦片的使用场景
    热力瓦片的特点是空间数据的实时聚合与渲染,主要应用于拥有海量矢量数据并需要实时统计分析的业务场景,比如:
  2. 交通运输类:根据运输工具(车、船等)的历史轨迹线,聚合出全域范围内的实时热力,并可根据时间(冬季、夏季)、起点/终点、类型(货车、客车)等附带条件进行过滤后实时生成相应的热力;
  3. 城市管理类:根据房屋建筑底面数据聚合出全域范围内城市/农村的建筑密度、建筑平均高度、建筑总面积等单项指标,并可结合地块信息聚合出容积率等复合指标;
  4. 共享出行类:根据共享出行设备的轨迹点,聚合出全域范围内设备的停靠区域热力,并可根据设备事件(开锁/关锁、上车/下车、事故、损坏)、流向等条件分析共享出行设备的调度运维策略;
    2.3 热力瓦片的技术优势
    相较于基于H3或S2网格预打码聚合的方式,HMT热力瓦片拥有如下优势:
  5. 效率极高,无需要预打码,不增加存储成本。HMT的聚合技术与H3/S2等网格聚合方式在技术特点及应用场景方面都有不同,网格聚合方式往往面向需要以网格编码作为检索条件的应用场景,因为它需要预先设定某一精度层级,之后在该精度下针对矢量数据进行赋码,再根据编码进行相关统计;而HMT不需要提前针对数据预打码,完全可以根据当前视口范围进行聚合,随着视口的放大缩小,聚合会实时进行,整个过程针对各类几何对象效率一致,均可达到亿级规模秒级聚合渲染;
  6. 方便宜用,聚合结果直接可视化。HMT提供了聚合结果快速瓦片化的能力,可以将聚合结果直接与前端渲染引擎进行可视化对接,保证所见即所得。同时HMT还提供了一系列的统计函数,帮助用户快速自动化生成最佳的渲染色表,确保前端的最优表现;
    经多个客户真实场景测试,HMT的聚合有着极高的效率,基本可以实现亿级规模全图聚合秒级完成:
    应用场景
    数据量
    瓦片范围
    聚合效率
    轨迹聚合
    轨迹线:45万
    轨迹点:3100万
    全球级别
    512512瓦片
    372ms
    建筑底面聚合
    建筑底面:3.08亿
    全球级别,
    512
    512瓦片
    17s
    注:上述数据均为全球展示尺度下全量数据聚合效率,随着地图不断放大,效率不断提升;
    2.4 热力瓦片的功能介绍
    热力瓦片包含一系列的SQL函数,用于解决热力瓦片的生成与统计问题,具体包括:
    • ST_AsHMT:将一组几何对象或轨迹对象按照指定范围和指定分辨率转为热力矩阵瓦片;
    • ST_HMTAsArray:将热力图瓦片转为基于数组矩阵的表示方法,方便进行查看;
    • ST_HMTStats:计算热力图瓦片统计信息;
    • ST_HMTAsRaster:将热力瓦片转为Raster对象,方便进行查看以及计算操作;
  7. 热力瓦片最佳实践
    3.1 操作步骤
  8. 将几何或轨迹数据入库到数据库中,建议使用FDW的方式进行入库。确保所有的对象都具备相同的空间参考系统(可以通过ST_Srid函数进行确认)
  9. 对几何列或轨迹列创建空间索引
    CREATE INDEX index_name ON table_name USING GIST(column_name)
  10. 根据空间范围进行热力瓦片的查询
    可以针对网格内的对象数量的进行热力聚合
    SELECT ST_AsHMT(column_name, --geometry type
    ST_MakeEnvelope(0, 0, 10, 10, 4326), -- Extent
    512, -- Width
    512 -- height
    )
    FROM table_name
    WHERE column_name && ST_MakeEnvelope(0, 0, 10, 10, 4326);
    也可以对某个网格内的数值进行聚合,使用value字段中的数值进行求和操作
    SELECT ST_AsHMT(column_name, --geometry type
    ST_MakeEnvelope(0, 0, 10, 10, 4326), -- Extent
    512, -- Width
    512, -- height
    value -- value column
    )
    FROM table_name
    WHERE column_name && ST_MakeEnvelope(0, 0, 10, 10, 4326);
    其中ST_MakeEnvelope可以使用ST_TileEnvelope函数获取瓦片范围。
    同样可以增加其他过滤条件:
    SELECT ST_AsHMT(column_name, --geometry type
    ST_MakeEnvelope(0, 0, 10, 10, 4326), -- Extent
    512, -- Width
    512, -- height
    value -- value column
    )
    FROM table_name
    WHERE column_name && ST_MakeEnvelope(0, 0, 10, 10, 4326);
    AND name like 'xxxx%' AND value > 100;
    3.2 使用技巧
    • 在数据量较大时采用并行提升性能,以下以并行度为16为例:
    SET max_worker_processes = 300; -- Maximum number of background processes
    set max_parallel_workers = 260; -- maximum number of workers
    set max_parallel_workers_per_gather = 16; --maximum number of workers that can be started by a single Gather or Gather Merge node
    alter table table_name set (parallel_workers=16);
    set force_parallel_mode = on;
    在实际使用中可以根据视口范围进行设置,如较高层级下使用16并行,较低层级下不使用并行等。
    在CPU足够的情况下,为了确保每个查询都可以使用并行,需要将max_worker_processes 和 max_parallel_workers 设置为并行度和并发数的乘积。 参考 postgresql的官方文档
    https://www.postgresql.org/docs/current/runtime-config-resource.html
    • 瓦片大小
    通常情况下使用512512 的瓦片重采样到256256的瓦片来避免锯齿的问题。但在在特殊情况下,如数据量非常大时,每个瓦片计算非常耗时,可以使用大瓦片(10241024)来降低瓦片的获取数量提升性能。
    • 使用&& 操作符进行空间过滤
    由于ST_AsHMT的计算比ST_Intersects要快很多, 在索引过滤时使用 && 替代ST_Intersects 过滤对象
    SELECT ST_AsHMT(column_name, --geometry type
    ST_MakeEnvelope(0, 0, 10, 10, 4326), -- Extent
    512, -- Width
    512, -- height
    value -- value column
    )
    FROM table_name
    WHERE column_name && ST_MakeEnvelope(0, 0, 10, 10, 4326);
    • 查询范围进行空间参考转换
    当查询范围和几何对象空间范围不一致时,将查询范围进行空间参考转换后查询。否则自动转换可能会引起性能较低。获取瓦片后将图片转换为指定的空间参考进行展示
    SELECT ST_AsHMT(column_name, -- srid = 4326
    ST_Transform(ST_TileEnvelope(6, 48, 32), 4326), -- Extent
    512, -- Width
    512, -- height
    value -- value column
    )
    FROM table_name
    WHERE column_name && ST_Transform(ST_TileEnvelope(6, 48, 32), 4326));
    • 对空间表进行vaccum full和cluster操作
    Vaccum操作可以回收空闲空间,降低磁盘文件大小,在查询时能降低IO数量。
    Cluster操作可以将数据组织与索引保持一致,相邻的空间数据会保存在相邻的数据页面中,访问时可以降低数据库的磁盘访问。
    VACUUM full table_name;
    Cluster table_name using index_name;
    3.3 发布服务进行浏览
    我们使用Node.js编写一个简易的应用,演示热力瓦片的实际使用场景。
    3.3.1 文件结构
    └── hmt_server
    ├── app.js
    ├── hmt.proto
    ├── index.html
    └── package.json
    其中:hmt.proto为上文中ST_AsHMT一节中介绍的proto文件,其他文件内容将在下文给出。
    3.3.2 后端代码
    {
    "name": "hmt_server",
    "version": "1.0.0",
    "main": "app.js",
    "license": "ISC",
    "dependencies": {
    "chroma-js": "^2.4.2",
    "express": "^4.18.2",
    "lru-cache": "^10.1.0",
    "pg": "^8.11.3",
    "protobufjs": "^7.2.5",
    "sharp": "^0.32.6"
    }
    }
    const express = require('express');
    const { Pool } = require('pg');
    const chroma = require('chroma-js');
    const sharp = require("sharp");
    const protobuf = require('protobufjs');
    const { LRUCache } = require('lru-cache');
    // 设定数据库连接
    const CONNECTION = {
    user: 'YOUR_USER',
    password: 'YOUR_PWD',
    host: 'YOUR_HOST',
    database: 'YOUR_DB',
    port: YOUR_PORT
    };
    // 目标表名
    const TABLE_NAME = 'YOUR_TABLE';
    // 目标几何字段名
    const GEOMETRY_COLUMN = 'YOUR_GEOM_COLUMN';
    // 设定无数据值
    const NO_DATA_VALUE = 0;
    // 目标几何字段空间参考
    const SRID = 4326
    // 设定色带
    const COLOR_MAP = [
    ['#536edb', 1],
    ['#5d96a5', 3],
    ['#68be70', 5],
    ['#91d54d', 7],
    ['#cddf37', 9],
    ['#fede28', 11],
    ['#fda938', 13],
    ['#fb7447', 15],
    ['#f75a40', 17],
    ['#f24734', 19],
    ['#e9352a', 21],
    ['#da2723', 23],
    ['#cb181d', 25]
    ];
    // 创建数据库连接池,默认为10个连接
    const pool = new Pool(CONNECTION);
    // 配置颜色转换
    const [colors, domains] = COLOR_MAP.reduce(([c, d], [colors, domains]) =>
    [[...c, colors], [...d, domains]], [[], []]);
    const colorMap = chroma.scale(colors).domain(domains).mode('rgb')
    // 加载protobuf
    const hmtDecoder = protobuf.loadSync('./hmt.proto').lookupType('HMT');
    // 创建一个1x1的透明png,作为空瓦片返回
    const emptyPng = Buffer.from('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAADUlEQVQImWP4//8/AwAI/AL+hc2rNAAAAABJRU5ErkJggg==', 'base64');
    // 对于小比例尺瓦片(z<5),因更新相对不明显,设定一个24小时过期的缓存
    const globalCache = new LRUCache({ max: 1000, ttl: 1000
    3600 24 });
    // 对于更大比例尺瓦片(z>=5),设定一个12小时过期的缓存,也可根据实际情况自行修改
    const localCache = new LRUCache({ max: 2000, ttl: 1000
    3600 * 12 });
    // 注册Express路由
    express()
    // 响应HTML页面
    .get("/", (_, res) => res.sendFile('index.html', { root: __dirname }))
    // 响应热力瓦片服务
    .get('/hmt/:z/:x/:y', async ({ params: { z, x, y } }, res) => {
    const cache = z < 5 ? globalCache : localCache;
    const key = ${z},${x},${y}
    if (!cache.has(key)) {
    // 设定并行度,并调用ST_AsHMT函数,请求该区域256x256的热力瓦片
    const parallel = z <= 5 ? 10 : 5;
    const sql = set max_parallel_workers = ${parallel}; set max_parallel_workers_per_gather = ${parallel}; WITH _PARAMS(_BORDER) as (VALUES(ST_Transform(ST_TileEnvelope(${key}),${SRID}))) SELECT ST_AsHMT(${GEOMETRY_COLUMN},_BORDER,256,256) tile FROM ${TABLE_NAME},_PARAMS WHERE _BORDER && ${GEOMETRY_COLUMN};
    // 跳过set语句,获取ST_AsHMT函数的结果
    const { rows: [{ tile }] } = (await pool.query(sql))[2];
    // 若该区域无数据则直接返回空瓦片
    if (!tile) cache.set(key, emptyPng);
    else {
     // 解析protobuf结果
     const { type, doubleValues, intValues } = hmtDecoder.decode(tile);
     const { values } = type == 1 ? doubleValues : intValues;
     // 将数值转换为对应的颜色,并剔除无数据值
     const pixels = values.reduce((_pixels, value) => {
       _pixels.push(...colorMap(value).rgb());
       _pixels.push(value <= NO_DATA_VALUE ? 0 : 255);
       return _pixels;
     }, [])
     // 渲染为png瓦片
     const rawConfig = { raw: { width: 256, height: 256, channels: 4 } };
     const renderedPng = await sharp(Uint8Array.from(pixels), rawConfig)
       .png().toBuffer();
     cache.set(key, renderedPng);
    
    }
    }
    const tile = cache.get(key)
    res.set("Content-Type", "image/png").send(tile);
    })
    // 监听5500端口
    .listen(5500, () => console.log('HMT server started.'));
    其中:
    • 色带为连续色带,支持十六进制字符串颜色、CSS3名称颜色等表达方式,可参见chroma.js文档。
    • 若想瓦片渲染效果更加平滑,可以以512x512请求数据,再降采样到256x256分辨率,只是会增加响应时间。
    • 并行度的设定需要根据数据量大小,数据库实例配置及对响应速度的需求来调整。
    • 本例在Z<=5时适当降低并行度。
    3.3.3 前端代码
    我们使用Mapbox作为前端地图SDK,其token可在此处申请查看。
    由于热力瓦片最终被渲染为PNG格式,因此兼容其他绝大多数地图SDK。
    <!DOCTYPE html>













3.3.4 安装与发布
https://www.bilibili.com/read/cv38852834
https://www.bilibili.com/read/cv38852896
https://www.bilibili.com/read/cv38852956

定位到hmt_server目录

cd ./hmt_server

安装依赖库

npm i

运行热力瓦片服务

node .

此时可以打开浏览器,登录地址 http://localhost:5500/ 查看效果

3.4 效果预览
3.4.1 船舶轨迹线实时聚合
• 3100万轨迹点,45万轨迹线实时聚合
3.4.2 建筑底面实时聚合
• 3.08亿建筑底面实时聚合
  • 总结
    目前,Ganos已经发展到了v6.0版本,支撑了数十个行业领域的数千个应用场景,稳定、成本、性能与易用性一直Ganos长期坚持的目标,HMT热力瓦片就是Ganos在大规模空间数据高效聚合与可视化领域的内核级核心竞争力,它为客户大规模数据分析挖掘提供了真正高效、易用的方案,欢迎各位用户体验。
  • 试用体验
    可以访问PolarDB免费试用页面,选择试用“云原生数据库PolarDB PostgreSQL版”,体验Ganos HMT实时热力统计查询能力。
  • 相关文章
    |
    15天前
    |
    机器学习/深度学习 Java API
    阿里云文档智能解析——大模型版能力最佳实践与体验评测
    阿里云文档智能解析(大模型版)在处理非结构化数据方面表现优异,尤其是在性能和可扩展性上具有明显优势。虽然存在一些待完善之处,但其强大的基础能力和广泛的适用场景使其成为企业数字转型过程中的有力助手。随着技术的不断进步和完善,相信它会在更多领域展现出更大的价值。
    51 5
    阿里云文档智能解析——大模型版能力最佳实践与体验评测
    |
    9天前
    |
    物联网 5G UED
    深入解析载波聚合及其对无线通信性能的提升
    深入解析载波聚合及其对无线通信性能的提升
    23 1
    |
    15天前
    |
    人工智能 自然语言处理 监控
    文档解析(大模型版)能力最佳实践测评
    文档解析(大模型版)能力最佳实践测评
    39 7
    |
    1天前
    |
    SQL 存储 数据可视化
    Ganos H3地理网格能力解析与最佳实践
    Ganos H3地理网格是一种基于六边形结构的高效地理空间数据处理技术,适用于物流、社交网络、数据分析及应急响应等多种场景。Ganos H3利用独特的六边形网格体系实现更均匀的数据分布和固定邻居关系,优化了空间数据分析、路径规划等功能。Ganos地理网格引擎支持GeoSOT和H3两种网格,具备丰富的打码方式、高性能查询及聚合分析能力,并能与几何和栅格数据融合,大幅提升了数据处理效率和存储成本效益。借助Ganos H3,企业和开发者可以更好地管理和利用地理空间数据,提高位置相关决策的准确性和效率。
    |
    28天前
    |
    开发者 图形学 API
    从零起步,深度揭秘:运用Unity引擎及网络编程技术,一步步搭建属于你的实时多人在线对战游戏平台——详尽指南与实战代码解析,带你轻松掌握网络化游戏开发的核心要领与最佳实践路径
    【8月更文挑战第31天】构建实时多人对战平台是技术与创意的结合。本文使用成熟的Unity游戏开发引擎,从零开始指导读者搭建简单的实时对战平台。内容涵盖网络架构设计、Unity网络API应用及客户端与服务器通信。首先,创建新项目并选择适合多人游戏的模板,使用推荐的网络传输层。接着,定义基本玩法,如2D多人射击游戏,创建角色预制件并添加Rigidbody2D组件。然后,引入网络身份组件以同步对象状态。通过示例代码展示玩家控制逻辑,包括移动和发射子弹功能。最后,设置服务器端逻辑,处理客户端连接和断开。本文帮助读者掌握构建Unity多人对战平台的核心知识,为进一步开发打下基础。
    61 0
    |
    29天前
    |
    监控 网络协议 Java
    Tomcat源码解析】整体架构组成及核心组件
    Tomcat,原名Catalina,是一款优雅轻盈的Web服务器,自4.x版本起扩展了JSP、EL等功能,超越了单纯的Servlet容器范畴。Servlet是Sun公司为Java编程Web应用制定的规范,Tomcat作为Servlet容器,负责构建Request与Response对象,并执行业务逻辑。
    Tomcat源码解析】整体架构组成及核心组件
    |
    1月前
    |
    存储 NoSQL Redis
    redis 6源码解析之 object
    redis 6源码解析之 object
    56 6
    |
    14天前
    |
    存储 缓存 Java
    什么是线程池?从底层源码入手,深度解析线程池的工作原理
    本文从底层源码入手,深度解析ThreadPoolExecutor底层源码,包括其核心字段、内部类和重要方法,另外对Executors工具类下的四种自带线程池源码进行解释。 阅读本文后,可以对线程池的工作原理、七大参数、生命周期、拒绝策略等内容拥有更深入的认识。
    什么是线程池?从底层源码入手,深度解析线程池的工作原理
    |
    18天前
    |
    开发工具
    Flutter-AnimatedWidget组件源码解析
    Flutter-AnimatedWidget组件源码解析
    |
    14天前
    |
    设计模式 Java 关系型数据库
    【Java笔记+踩坑汇总】Java基础+JavaWeb+SSM+SpringBoot+SpringCloud+瑞吉外卖/谷粒商城/学成在线+设计模式+面试题汇总+性能调优/架构设计+源码解析
    本文是“Java学习路线”专栏的导航文章,目标是为Java初学者和初中高级工程师提供一套完整的Java学习路线。
    160 37

    热门文章

    最新文章

    推荐镜像

    更多