Skip to content
ClickHouse Docs
ClickHouse DocsClickHouse Docs

Полигональные словари

Полигональный словарь 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))
...

При настройке полигонального словаря ключ должен быть одного из двух типов:

  • Простой полигон. Это массив точек.
  • MultiPolygon. Это массив полигонов. Каждый полигон представляет собой двумерный массив точек. Первый элемент этого массива — внешняя граница полигона, а последующие элементы задают области, которые должны быть из него исключены.

Точки можно задавать в виде массива или кортежа координат. В текущей реализации поддерживаются только двумерные точки.

Можно загружать собственные данные во всех форматах, поддерживаемых ClickHouse.

Доступны 3 типа хранилищ в памяти:

Layout Описание
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 — для этого просто включите store_polygon_key_column = 1 в конфигурации словаря или соответствующем DDL-запросе.

Querysql
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;
Responsetext
┌─key─────────────────────────────┬─name──┐
│ [[[(3,1),(0,1),(0,-1),(3,-1)]]] │ Value │
└─────────────────────────────────┴───────┘
Navigation