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

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共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实时热力统计查询能力。
  • 相关文章
    |
    17天前
    |
    机器学习/深度学习 安全 大数据
    揭秘!企业级大模型如何安全高效私有化部署?全面解析最佳实践,助你打造智能业务新引擎!
    【10月更文挑战第24天】本文详细探讨了企业级大模型私有化部署的最佳实践,涵盖数据隐私与安全、定制化配置、部署流程、性能优化及安全措施。通过私有化部署,企业能够完全控制数据,确保敏感信息的安全,同时根据自身需求进行优化,提升计算性能和处理效率。示例代码展示了如何利用Python和TensorFlow进行文本分类任务的模型训练。
    53 6
    |
    11天前
    |
    PHP 开发者 容器
    PHP命名空间深度解析与最佳实践####
    本文深入探讨了PHP中命名空间(namespace)的机制、应用场景及最佳实践,旨在帮助开发者有效避免命名冲突,提升代码的组织性和可维护性。通过实例讲解,本文将引导您理解如何在实际项目中灵活运用命名空间,以及如何遵循业界公认的最佳实践来优化您的PHP代码结构。 ####
    |
    10天前
    |
    PHP 开发者
    PHP 7新特性深度解析及其最佳实践
    【10月更文挑战第31天】本文将深入探讨PHP 7带来的革新,从性能提升到语法改进,再到错误处理机制的变革。我们将通过实际代码示例,展示如何高效利用这些新特性来编写更加健壮和高效的PHP应用。无论你是PHP新手还是资深开发者,这篇文章都将为你打开一扇窗,让你看到PHP 7的强大之处。
    |
    18天前
    |
    监控 安全 Serverless
    "揭秘D2终端大会热点技术:Serverless架构最佳实践全解析,让你的开发效率翻倍,迈向技术新高峰!"
    【10月更文挑战第23天】D2终端大会汇聚了众多前沿技术,其中Serverless架构备受瞩目。它让开发者无需关注服务器管理,专注于业务逻辑,提高开发效率。本文介绍了选择合适平台、设计合理函数架构、优化性能及安全监控的最佳实践,助力开发者充分挖掘Serverless潜力,推动技术发展。
    39 1
    |
    22天前
    |
    监控 安全 Java
    构建高效后端服务:微服务架构深度解析与最佳实践###
    【10月更文挑战第19天】 在数字化转型加速的今天,企业对后端服务的响应速度、可扩展性和灵活性提出了更高要求。本文探讨了微服务架构作为解决方案,通过分析传统单体架构面临的挑战,深入剖析微服务的核心优势、关键组件及设计原则。我们将从实际案例入手,揭示成功实施微服务的策略与常见陷阱,为开发者和企业提供可操作的指导建议。本文目的是帮助读者理解如何利用微服务架构提升后端服务的整体效能,实现业务快速迭代与创新。 ###
    54 2
    |
    1月前
    |
    存储 缓存 监控
    深入解析:Elasticsearch集群性能调优策略与最佳实践
    【10月更文挑战第8天】Elasticsearch 是一个分布式的、基于 RESTful 风格的搜索和数据分析引擎,它能够快速地存储、搜索和分析大量数据。随着企业对实时数据处理需求的增长,Elasticsearch 被广泛应用于日志分析、全文搜索、安全信息和事件管理(SIEM)等领域。然而,为了确保 Elasticsearch 集群能够高效运行并满足业务需求,需要进行一系列的性能调优工作。
    71 3
    |
    1月前
    |
    域名解析 网络协议 安全
    DNS查询工具简介
    DNS查询工具简介
    |
    28天前
    |
    SQL 数据可视化 BI
    SQL语句及查询结果解析:技巧与方法
    在数据库管理和数据分析中,SQL语句扮演着至关重要的角色
    |
    1月前
    |
    缓存 Java 程序员
    Map - LinkedHashSet&Map源码解析
    Map - LinkedHashSet&Map源码解析
    66 0
    |
    1月前
    |
    算法 Java 容器
    Map - HashSet & HashMap 源码解析
    Map - HashSet & HashMap 源码解析
    52 0

    推荐镜像

    更多