Перейти к основному содержимому
Перейти к основному содержимому

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

Словарь polygon (POLYGON) оптимизирован для запросов на определение принадлежности точки полигону — по сути, для операций «обратного геокодирования». По заданной координате (широта/долгота) он эффективно определяет, какой полигон или регион (из набора множества полигонов, например границ стран или регионов) содержит данную точку. Он хорошо подходит для привязки координат местоположения к соответствующему региону.

Пример настройки полигонального словаря:

Совет

Если вы используете словари с ClickHouse Cloud, используйте DDL-запрос для их создания и создавайте словари от имени пользователя default. Также проверьте список поддерживаемых источников словарей в руководстве по совместимости с ClickHouse Cloud.

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 типа хранилища в памяти:

СхемаОписание
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-запросе.

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 │
└─────────────────────────────────┴───────┘