ClickHouse/docs/ru/sql-reference/dictionaries/external-dictionaries/external-dicts-dict-polygon.md
Andrey Chulkov 1fe8e15e68 smallfix
2020-05-26 01:57:53 +03:00

5.4 KiB
Raw Blame History

овари полигонов

Словари полигонов позволяют эффективно искать полигон, в который попадают данные точки, среди множества полигонов. Для примера: определение района города по географическим координатам.

Пример конфигурации:

<dictionary>
    <structure>
        <key>
            <name>key</name>
            <type>Array(Array(Array(Array(Float64))))</type>
        </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 />
    </layout>

</dictionary>

Соответствущий DDL-запрос:

CREATE DICTIONARY polygon_dict_name (
    key Array(Array(Array(Array(Float64)))),
    name String,
    value UInt64
)
PRIMARY KEY key
LAYOUT(POLYGON())
...

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

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

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

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

Доступно 3 типа хранения данных в памяти: (TODO: время, память)

  • POLYGON. Это наивная реализация, в которой на каждый запрос делается линейный проход по всем полигонам, и для каждого проверяется принадлежность без использования дополнительных индексов.

  • POLYGON_INDEX_EACH. Для каждого полигона строится отдельный индекс, который позволяет быстро проверять принадлежность в большинстве случаев (оптимизирован под географические регионы). Также строится сетка, которая значительно сужает количество рассматриваемых полигонов. Сетка строится рекурсивным делением ячейки на 16 равных частей и конфигурируется двумя параметрами: MAX_DEPTH — максимальная глубина рекурсии и MIN_INTERSECTIONS — минимальное число полигонов, которое должна пересекать ячейка для дальнейшего деления. Для ответа на запрос происходит обращение к индексу для оставшегося набора полигонов.

  • 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 будет найден полигон минимальной площади, содержащий данную точку, и выведены запрошенные аттрибуты.