mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-17 05:03:20 +00:00
86 lines
5.4 KiB
Markdown
86 lines
5.4 KiB
Markdown
# Cловари полигонов {#slovari-polygonov}
|
||
|
||
Словари полигонов позволяют эффективно искать полигон, в который попадают данные точки, среди множества полигонов.
|
||
Для примера: определение района города по географическим координатам.
|
||
|
||
Пример конфигурации:
|
||
|
||
``` xml
|
||
<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-запрос](../../../sql-reference/statements/create.md#create-dictionary-query):
|
||
``` sql
|
||
CREATE DICTIONARY polygon_dict_name (
|
||
key Array(Array(Array(Array(Float64)))),
|
||
name String,
|
||
value UInt64
|
||
)
|
||
PRIMARY KEY key
|
||
LAYOUT(POLYGON())
|
||
...
|
||
```
|
||
|
||
При конфигурации словаря полигонов ключ должен иметь один из двух типов:
|
||
- Простой полигон. Представляет из себя массив точек.
|
||
- Мультиполигон. Представляет из себя массив полигонов. Каждый полигон задается двумерным массивом точек — первый элемент этого массива задает внешнюю границу полигона,
|
||
последующие элементы могут задавать дырки, вырезаемые из него.
|
||
|
||
Точки могут задаваться массивом или кортежем из своих координат. В текущей реализации поддерживается только двумерные точки.
|
||
|
||
Пользователь может [загружать свои собственные данные](../../../sql-reference/dictionaries/external-dictionaries/external-dicts-dict-sources.md) во всех поддерживаемых ClickHouse форматах.
|
||
|
||
|
||
Доступно 3 типа [хранения данных в памяти](../../../sql-reference/dictionaries/external-dictionaries/external-dicts-dict-layout.md): (TODO: время, память)
|
||
|
||
- POLYGON. Это наивная реализация, в которой на каждый запрос делается линейный проход по всем полигонам, и для каждого проверяется принадлежность без использования дополнительных индексов.
|
||
|
||
- POLYGON_INDEX_EACH. Для каждого полигона строится отдельный индекс, который позволяет быстро проверять принадлежность в большинстве случаев (оптимизирован под географические регионы).
|
||
Также строится сетка, которая значительно сужает количество рассматриваемых полигонов.
|
||
Сетка строится рекурсивным делением ячейки на 16 равных частей и конфигурируется двумя параметрами:
|
||
MAX_DEPTH — максимальная глубина рекурсии и MIN_INTERSECTIONS — минимальное число полигонов, которое должна пересекать ячейка для дальнейшего деления.
|
||
Для ответа на запрос происходит обращение к индексу для оставшегося набора полигонов.
|
||
|
||
- POLYGON_INDEX_CELL. В этом размещении также строится сетка, описанная выше. Доступны такие же параметры. Для каждой ячейки-листа строится индекс на попадающих в неё кусках полигонов, который позволяет быстро среди них искать.
|
||
|
||
|
||
Запросы к словарю осуществляются с помощью стандартных [функций](../../../sql-reference/functions/ext-dict-functions.md) для работы со внешними словарями.
|
||
Важным отличием является то, что здесь ключами будут являются точки, для которых хочется найти содержащий их полигон.
|
||
|
||
Пример работы со словарем, определенным выше:
|
||
``` sql
|
||
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` будет найден полигон минимальной площади, содержащий данную точку, и выведены запрошенные аттрибуты.
|