polygon (POLYGON) 字典针对点是否落在多边形内的查询进行了优化,本质上属于“反向地理编码”查找。
给定一个坐标 (纬度/经度) ,它可以高效找出包含该点的多边形/区域 (从多个多边形组成的集合中,例如国家或区域边界) 。
它非常适合将位置坐标映射到其所在区域。
配置 Polygon 字典的示例:
CREATE DICTIONARY polygon_dict_name (
key Array(Array(Array(Array(Float64)))),
name String,
value UInt64
)
PRIMARY KEY key
LAYOUT(POLYGON(STORE_POLYGON_KEY_COLUMN 1))
...<dictionary>
<structure>
<key>
<attribute>
<name>key</name>
<type>Array(Array(Array(Array(Float64))))</type>
</attribute>
</key>
<attribute>
<name>name</name>
<type>String</type>
<null_value></null_value>
</attribute>
<attribute>
<name>value</name>
<type>UInt64</type>
<null_value>0</null_value>
</attribute>
</structure>
<layout>
<polygon>
<store_polygon_key_column>1</store_polygon_key_column>
</polygon>
</layout>
...
</dictionary>配置 Polygon 字典时,键必须是以下两种类型之一:
- 简单多边形。它是一个点数组。
- MultiPolygon。它是一个多边形数组。每个多边形都是一个二维点数组。该数组的第一个元素是多边形的外边界,后续元素表示需要从中排除的区域。
点既可以指定为坐标数组,也可以指定为坐标 Tuple。当前实现仅支持二维点。
用户可以上传自己的数据,格式可以是 ClickHouse 支持的任意格式。
可用的内存存储共有 3 种类型:
| Layout | Description |
|---|---|
POLYGON_SIMPLE |
朴素实现。每次查询都会线性遍历所有多边形,在没有额外索引的情况下检查是否包含该点。 |
POLYGON_INDEX_EACH |
为每个多边形单独构建索引,在大多数情况下都能快速完成包含关系检查 (针对地理区域做了优化) 。系统会在区域上叠加一个网格,并递归地将单元划分为 16 个相等部分。当递归深度达到 MAX_DEPTH,或某个单元穿过的多边形数量不超过 MIN_INTERSECTIONS 时,停止划分。 |
POLYGON_INDEX_CELL |
同样会使用上述相同选项创建网格。对于每个叶子单元,都会对落入其中的所有多边形片段构建索引,从而实现快速查询响应。 |
POLYGON |
POLYGON_INDEX_CELL 的同义词。 |
字典查询使用用于操作字典的标准函数来执行。 一个重要区别是,这里的键是你希望查找其所属多边形的点。
示例
使用上述定义的字典的示例:
CREATE TABLE points (
x Float64,
y Float64
)
...
SELECT tuple(x, y) AS key, dictGet(dict_name, 'name', key), dictGet(dict_name, 'value', key) FROM points ORDER BY x, y;执行上一条命令后,将会为 points 表中的每个点找到包含该点的最小面积多边形,并输出所需的属性。
示例
你可以通过 SELECT 查询从多边形字典中读取列;只需在字典配置或相应的 DDL 查询中启用 store_polygon_key_column = 1 即可。
CREATE TABLE polygons_test_table
(
key Array(Array(Array(Tuple(Float64, Float64)))),
name String
) ENGINE = MergeTree
ORDER BY tuple();
INSERT INTO polygons_test_table VALUES ([[[(3, 1), (0, 1), (0, -1), (3, -1)]]], 'Value');
CREATE DICTIONARY polygons_test_dictionary
(
key Array(Array(Array(Tuple(Float64, Float64)))),
name String
)
PRIMARY KEY key
SOURCE(CLICKHOUSE(TABLE 'polygons_test_table'))
LAYOUT(POLYGON(STORE_POLYGON_KEY_COLUMN 1))
LIFETIME(0);
SELECT * FROM polygons_test_dictionary;┌─key─────────────────────────────┬─name──┐
│ [[[(3,1),(0,1),(0,-1),(3,-1)]]] │ Value │
└─────────────────────────────────┴───────┘