Важно: Данный раздел актуален для Платформы данных On-Premise.
Словарь — это отображение (ключ -> атрибуты
), которое удобно использовать для различного вида справочников.
RT.WideStore поддерживает специальные функции для работы со словарями, которые можно использовать в запросах. Проще и эффективнее использовать словари с помощью функций, чем JOIN
с таблицами-справочниками.
RT.WideStore поддерживает:
Существует возможность подключать собственные словари из различных источников данных. Источником данных для словаря может быть локальный текстовый/исполняемый файл, HTTP(s) ресурс или другая СУБД. Подробнее смотрите в разделе «Источники внешних словарей».
RT.WideStore :
Конфигурация внешних словарей может находиться в одном или нескольких xml-файлах. Путь к конфигурации указывается в параметре dictionaries_config.
Словари могут загружаться при старте сервера или при первом использовании, в зависимости от настройки dictionaries_lazy_load.
Системная таблица system.dictionaries содержит информацию о словарях, сконфигурированных на сервере. Для каждого словаря там можно найти:
Конфигурационный файл словарей имеет вид:
<widestore>
<comment>Необязательный элемент с любым содержимым. Игнорируется сервером WideStore.</comment>
<!--Необязательный элемент, имя файла с подстановками-->
<include_from>/etc/metrika.xml</include_from>
<dictionary>
<!-- Конфигурация словаря -->
</dictionary>
...
<dictionary>
<!-- Конфигурация словаря -->
</dictionary>
</widestore>
В одном файле можно сконфигурировать произвольное количество словарей.
Если вы создаёте внешние словари DDL-запросами, то не задавайте конфигурацию словаря в конфигурации сервера.
Внимание:
Можно преобразовывать значения по небольшому словарю, описав его в запросе `SELECT` (см. функцию transform). Эта функциональность не связана с внешними словарями.
Смотрите также:
XML-конфигурация словаря имеет следующую структуру:
<dictionary>
<name>dict_name</name>
<structure>
<!-- Complex key configuration -->
</structure>
<source>
<!-- Source configuration -->
</source>
<layout>
<!-- Memory layout configuration -->
</layout>
<lifetime>
<!-- Lifetime of dictionary in memory -->
</lifetime>
</dictionary>
Соответствующий DDL-запрос имеет следующий вид:
CREATE DICTIONARY dict_name
(
... -- attributes
)
PRIMARY KEY ... -- complex or single key configuration
SOURCE(...) -- Source configuration
LAYOUT(...) -- Memory layout configuration
LIFETIME(...) -- Lifetime of dictionary in memory
name
— Идентификатор, под которым словарь будет доступен для использования. Используйте символы [a-zA-Z0-9_\-]
.Словари можно размещать в памяти множеством способов.
Рекомендуем flat, hashed и complex_key_hashed. Скорость обработки словарей при этом максимальна.
Размещение с кэшированием не рекомендуется использовать из-за потенциально низкой производительности и сложностей в подборе оптимальных параметров. Читайте об этом подробнее в разделе cache.
Повысить производительность словарей можно следующими способами:
GROUP BY
.GROUP BY
функции, достающей значение атрибута по ключу, эта функция автоматически выносится из GROUP BY
.При ошибках работы со словарями RT.WideStore генерирует исключения. Например, в следующих ситуациях:
cached
-словарю.Список внешних словарей и их статус можно посмотреть в таблице system.dictionaries.
Общий вид конфигурации:
<widestore>
<dictionary>
...
<layout>
<layout_type>
<!-- layout settings -->
</layout_type>
</layout>
...
</dictionary>
</widestore>
Соответствущий DDL-запрос:
CREATE DICTIONARY (...)
...
LAYOUT(LAYOUT_TYPE(param value)) -- layout settings
...
Ключ словарей не имеющих слово complex-key*
в названии имеет тип UInt64, complex-key*
словари позволяют произвольный тип ключа (составной, и из разных типов).
UInt64 ключи в XML словарях задаются тегом <id>
.
Пример конфигурации (поле key_column имеет тип UInt64):
...
<structure>
<id>
<name>key_column</name>
</id>
...
Составные complex
ключи в XML словарях задаются тегом <key>
.
Пример конфигурации составного ключа (ключ состоит из одного элемента с типом String):
...
<structure>
<key>
<attribute>
<name>country_code</name>
<type>String</type>
</attribute>
</key>
...
Словарь полностью хранится в оперативной памяти в виде плоских массивов. Объём памяти, занимаемой словарём, пропорционален размеру самого большого ключа (по объему).
Ключ словаря имеет тип UInt64 и его величина ограничена параметром max_array_size
(значение по умолчанию — 500 000). Если при создании словаря обнаружен ключ больше, то RT.WideStore бросает исключение и не создает словарь. Начальный размер плоских массивов словарей контролируется параметром initial_array_size (по умолчанию - 1024).
Поддерживаются все виды источников. При обновлении данные (из файла или из таблицы) считываются целиком.
Это метод обеспечивает максимальную производительность среди всех доступных способов размещения словаря.
Пример конфигурации:
<layout>
<flat>
<initial_array_size>50000</initial_array_size>
<max_array_size>5000000</max_array_size>
</flat>
</layout>
или
LAYOUT(FLAT(INITIAL_ARRAY_SIZE 50000 MAX_ARRAY_SIZE 5000000))
Словарь полностью хранится в оперативной памяти в виде хэш-таблиц. Словарь может содержать произвольное количество элементов с произвольными идентификаторами. На практике количество ключей может достигать десятков миллионов элементов.
Ключ словаря имеет тип UInt64.
Поддерживаются все виды источников. При обновлении данные (из файла, из таблицы) читаются целиком.
Пример конфигурации:
<layout>
<hashed/>
</layout>
или
LAYOUT(HASHED())
Аналогичен hashed
, но при этом занимает меньше места в памяти и генерирует более высокую загрузку CPU.
Ключ словаря имеет тип UInt64.
Пример конфигурации:
<layout>
<sparse_hashed />
</layout>
или
LAYOUT(SPARSE_HASHED())
Тип размещения предназначен для использования с составными ключами. Аналогичен hashed
.
Пример конфигурации:
<layout>
<complex_key_hashed />
</layout>
или
LAYOUT(COMPLEX_KEY_HASHED())
Тип размещения предназначен для использования с составными ключами. Аналогичен sparse_hashed.
Пример конфигурации:
<layout>
<complex_key_sparse_hashed />
</layout>
или
LAYOUT(COMPLEX_KEY_SPARSE_HASHED())
Словарь полностью хранится в оперативной памяти. Каждый атрибут хранится в массиве. Ключевой атрибут хранится в виде хеш-таблицы, где его значение является индексом в массиве атрибутов. Словарь может содержать произвольное количество элементов с произвольными идентификаторами. На практике количество ключей может достигать десятков миллионов элементов.
Ключ словаря имеет тип UInt64.
Поддерживаются все виды источников. При обновлении данные (из файла, из таблицы) считываются целиком.
Пример конфигурации:
<layout>
<hashed_array>
</hashed_array>
</layout>
или
LAYOUT(HASHED_ARRAY())
Тип размещения предназначен для использования с составными ключами. Аналогичен hashed_array.
Пример конфигурации:
<layout>
<complex_key_hashed_array />
</layout>
или
LAYOUT(COMPLEX_KEY_HASHED_ARRAY())
Словарь хранится в оперативной памяти в виде хэш-таблицы с упорядоченным массивом диапазонов и соответствующих им значений.
Ключ словаря имеет тип UInt64. Этот способ размещения работает также как и hashed и позволяет дополнительно к ключу использовать дипазоны по дате/времени (произвольному числовому типу).
Пример: таблица содержит скидки для каждого рекламодателя в виде:
+---------------+---------------------+-------------------+--------+
| advertiser id | discount start date | discount end date | amount |
+===============+=====================+===================+========+
| 123 | 2015-01-01 | 2015-01-15 | 0.15 |
+---------------+---------------------+-------------------+--------+
| 123 | 2015-01-16 | 2015-01-31 | 0.25 |
+---------------+---------------------+-------------------+--------+
| 456 | 2015-01-01 | 2015-01-15 | 0.05 |
+---------------+---------------------+-------------------+--------+
Чтобы использовать выборку по диапазонам дат, необходимо в structure определить элементы range_min
, range_max
. В этих элементах должны присутствовать элементы name
и type
(если type
не указан, будет использован тип по умолчанию – Date). type
может быть любым численным типом (Date/DateTime/UInt64/Int32/др.).
Пример:
<structure>
<id>
<name>Id</name>
</id>
<range_min>
<name>first</name>
<type>Date</type>
</range_min>
<range_max>
<name>last</name>
<type>Date</type>
</range_max>
...
или
CREATE DICTIONARY somedict (
id UInt64,
first Date,
last Date
)
PRIMARY KEY idLAYOUT(RANGE_HASHED())
RANGE(MIN first MAX last)
Для работы с такими словарями в функцию dictGetT
необходимо передавать дополнительный аргумент, для которого подбирается диапазон:
dictGetT('dict_name', 'attr_name', id, date)
Функция возвращает значение для заданных id
и диапазона дат, в который входит переданная дата.
Особенности алгоритма:
id
или для найденного id
не найден диапазон, то возвращается значение по умолчанию для словаря.NULL
или некорректная дата (1900-01-01), то диапазон считается открытым. Диапазон может быть открытым с обеих сторон.Пример конфигурации:
<widestore>
<dictionary>
...
<layout>
<range_hashed />
</layout>
<structure>
<id>
<name>Abcdef</name>
</id>
<range_min>
<name>StartTimeStamp</name>
<type>UInt64</type>
</range_min>
<range_max>
<name>EndTimeStamp</name>
<type>UInt64</type>
</range_max>
<attribute>
<name>XXXType</name>
<type>String</type>
<null_value />
</attribute>
</structure>
</dictionary>
</widestore>
или
CREATE DICTIONARY somedict(
Abcdef UInt64,
StartTimeStamp UInt64,
EndTimeStamp UInt64,
XXXType String DEFAULT ''
)
PRIMARY KEY Abcdef
RANGE(MIN StartTimeStamp MAX EndTimeStamp)
Словарь хранится в оперативной памяти в виде хэш-таблицы с упорядоченным массивом диапазонов и соответствующих им значений (см. range_hashed). Данный тип размещения предназначен для использования с составными ключами.
Пример конфигурации:
CREATE DICTIONARY range_dictionary
(
CountryID UInt64,
CountryKey String,
StartDate Date,
EndDate Date,
Tax Float64 DEFAULT 0.2
)
PRIMARY KEY CountryID, CountryKey
SOURCE(WIDESTORE(TABLE 'date_table'))
LIFETIME(MIN 1 MAX 1000)
LAYOUT(COMPLEX_KEY_RANGE_HASHED())
RANGE(MIN StartDate MAX EndDate);
Словарь хранится в кэше, состоящем из фиксированного количества ячеек. Ячейки содержат часто используемые элементы.
Ключ словаря имеет тип UInt64.
При поиске в словаре сначала просматривается кэш. На каждый блок данных, все не найденные в кэше или устаревшие ключи запрашиваются у источника с помощью SELECT attrs... FROM db.table WHERE id IN (k1, k2, ...)
. Затем, полученные данные записываются в кэш.
Если ключи не были найдены в словаре, то для обновления кэша создается задание и добавляется в очередь обновлений. Параметры очереди обновлений можно устанавливать настройками max_update_queue_size
, update_queue_push_timeout_milliseconds
, query_wait_timeout_milliseconds
, max_threads_for_updates
Для cache-словарей при помощи настройки allow_read_expired_keys
может быть задано время устаревания lifetime данных в кэше. Если с момента загрузки данных в ячейку прошло больше времени, чем lifetime
, то значение не используется, а ключ устаревает. Ключ будет запрошен заново при следующей необходимости его использовать.
Это наименее эффективный из всех способов размещения словарей. Скорость работы кэша очень сильно зависит от правильности настройки и сценария использования. Словарь типа cache
показывает высокую производительность лишь при достаточно большой частоте успешных обращений (рекомендуется 99% и выше). Посмотреть среднюю частоту успешных обращений (hit rate
) можно в таблице system.dictionaries.
Если параметр allow_read_expired_keys
выставлен в 1 (0 по умолчанию), то словарь поддерживает асинхронные обновления. Если клиент запрашивает ключи, которые находятся в кэше, но при этом некоторые из них устарели, то словарь вернет устаревшие ключи клиенту и запросит их асинхронно у источника.
Чтобы увеличить производительность кэша, используйте подзапрос с LIMIT
, а снаружи вызывайте функцию со словарём.
Поддерживаются все виды источников.
Пример настройки:
<layout>
<cache>
<!-- Размер кэша в количестве ячеек. Округляется вверх до степени двух. -->
<size_in_cells>1000000000</size_in_cells>
<!-- Позволить читать устаревшие ключи. -->
<allow_read_expired_keys>0</allow_read_expired_keys>
<!-- Максимальный размер очереди обновлений. -->
<max_update_queue_size>100000</max_update_queue_size>
<!-- Максимальное время (в миллисекундах) для отправки в очередь. -->
<update_queue_push_timeout_milliseconds>10</update_queue_push_timeout_milliseconds>
<!-- Максимальное время ожидания (в миллисекундах) для выполнения обновлений. -->
<query_wait_timeout_milliseconds>60000</query_wait_timeout_milliseconds>
<!-- Максимальное число потоков для обновления кэша словаря. -->
<max_threads_for_updates>4</max_threads_for_updates>
</cache>
</layout>
или
LAYOUT(CACHE(SIZE_IN_CELLS 1000000000))
Укажите достаточно большой размер кэша. Количество ячеек следует подобрать экспериментальным путём:
system.dictionaries
.Предупреждение:
Не используйте в качестве источника RT.WideStore, поскольку он медленно обрабатывает запросы со случайным чтением.
Тип размещения предназначен для использования с составными ключами. Аналогичен cache
.
Похож на cache
, но хранит данные на SSD, а индекс в оперативной памяти. Все параметры, относящиеся к очереди обновлений, могут также быть применены к SSD-кэш словарям.
Ключ словаря имеет тип UInt64.
<layout>
<ssd_cache>
<!-- Size of elementary read block in bytes. Recommended to be equal to SSD's page size. -->
<block_size>4096</block_size>
<!-- Max cache file size in bytes. -->
<file_size>16777216</file_size>
<!-- Size of RAM buffer in bytes for reading elements from SSD. -->
<read_buffer_size>131072</read_buffer_size>
<!-- Size of RAM buffer in bytes for aggregating elements before flushing to SSD. -->
<write_buffer_size>1048576</write_buffer_size>
<!-- Path where cache file will be stored. -->
<path>/var/lib/widestore/user_files/test_dict</path>
</ssd_cache>
</layout>
или
LAYOUT(SSD_CACHE(BLOCK_SIZE 4096 FILE_SIZE 16777216 READ_BUFFER_SIZE 1048576
PATH '/var/lib/widestore/user_files/test_dict'))
Тип размещения предназначен для использования с составными ключами. Похож на ssd_cache
.
Словарь не хранит данные локально и взаимодействует с источником непосредственно в момент запроса.
Ключ словаря имеет тип UInt64.
Поддерживаются все виды источников, кроме локальных файлов.
Пример конфигурации:
<layout>
<direct />
</layout>
или
LAYOUT(DIRECT())
Тип размещения предназначен для использования с составными ключами. Аналогичен direct
.
Тип размещения предназначен для сопоставления префиксов сети (IP адресов) с метаданными, такими как ASN.
Пример: таблица содержит префиксы сети и соответствующие им номера AS и коды стран:
+-----------------+-------+--------+
| prefix | asn | cca2 |
+=================+=======+========+
| 202.79.32.0/20 | 17501 | NP |
+-----------------+-------+--------+
| 2620:0:870::/48 | 3856 | US |
+-----------------+-------+--------+
| 2a02:6b8:1::/48 | 13238 | RU |
+-----------------+-------+--------+
| 2001:db8::/32 | 65536 | ZZ |
+-----------------+-------+--------+
При использовании такого макета структура должна иметь составной ключ.
Пример:
<structure>
<key>
<attribute>
<name>prefix</name>
<type>String</type>
</attribute>
</key>
<attribute>
<name>asn</name>
<type>UInt32</type>
<null_value />
</attribute>
<attribute>
<name>cca2</name>
<type>String</type>
<null_value>??</null_value>
</attribute>
...
</structure><layout>
<ip_trie>
<!-- Ключевой аттрибут `prefix` будет доступен через dictGetString -->
<!-- Эта опция увеличивает потреблямую память -->
<access_to_key_from_attributes>true</access_to_key_from_attributes>
</ip_trie>
</layout>
или
CREATE DICTIONARY somedict (
prefix String,
asn UInt32,
cca2 String DEFAULT '??'
)
PRIMARY KEY prefix
Этот ключ должен иметь только один атрибут типа String
, содержащий допустимый префикс IP. Другие типы еще не поддерживаются.
Для запросов необходимо использовать те же функции (dictGetT
с кортежем), что и для словарей с составными ключами:
dictGetT('dict_name', 'attr_name', tuple(ip))
Функция принимает либо UInt32
для IPv4, либо FixedString
(16)
для IPv6:
dictGetString('prefix', 'asn', tuple(IPv6StringToNum('2001:db8::1')))
Никакие другие типы не поддерживаются. Функция возвращает атрибут для префикса, соответствующего данному IP-адресу. Если есть перекрывающиеся префиксы, возвращается наиболее специфический.
Данные должны полностью помещаться в оперативной памяти.
RT.WideStore периодически обновляет словари. Интервал обновления для полностью загружаемых словарей и интервал инвалидации для кэшируемых словарей определяется в теге <lifetime>
в секундах.
Обновление словарей (кроме загрузки при первом использовании) не блокирует запросы - во время обновления используется старая версия словаря. Если при обновлении возникнет ошибка, то ошибка пишется в лог сервера, а запросы продолжат использовать старую версию словарей.
Пример настройки:
<dictionary>
...
<lifetime>300</lifetime>
...
</dictionary>
или
CREATE DICTIONARY (...)
...
LIFETIME(300)
...
Настройка <lifetime>0</lifetime>
(LIFETIME(0)
) запрещает обновление словарей.
Можно задать интервал, внутри которого RT.WideStore равномерно-случайно выберет время для обновления. Это необходимо для распределения нагрузки на источник словаря при обновлении на большом количестве серверов.
Пример настройки:
<dictionary>
...
<lifetime>
<min>300</min>
<max>360</max>
</lifetime>
...
</dictionary>
или
LIFETIME(MIN 300 MAX 360)
Если <min>0</min>
и <max>0</max>
, RT.WideStore не перезагружает словарь по истечении времени. В этом случае RT.WideStore может перезагрузить данные словаря, если изменился XML файл с конфигурацией словаря или если была выполнена команда SYSTEM RELOAD DICTIONARY
.
При обновлении словарей сервер RT.WideStore применяет различную логику в зависимости от типа источника:
SHOW TABLE STATUS
(для MySQL 8 необходимо отключить кеширование мета-информации в MySQL set global information_schema_stats_expiry=0
).Для других источников (ODBC, PostgreSQL, RT.WideStore и т.д.) можно настроить запрос, который позволит обновлять словари только в случае их фактического изменения, а не каждый раз. Чтобы это сделать необходимо выполнить следующие условия/действия:
<invalidate_query>
настроек источника.Пример настройки:
<dictionary>
...
<odbc>
...
<invalidate_query>SELECT update_time FROM dictionary_source where id = 1</invalidate_query>
</odbc>
...
</dictionary>
или
...
SOURCE(ODBC(... invalidate_query 'SELECT update_time FROM dictionary_source where id = 1'))
...
Для словарей Cache
, ComplexKeyCache
, SSDCache
и SSDComplexKeyCache
поддерживается как синхронное, так и асинхронное обновление.
Словари Flat
, Hashed
и ComplexKeyHashed
могут запрашивать только те данные, которые были изменены после предыдущего обновления. Если update_field
указано как часть конфигурации источника словаря, к запросу данных будет добавлено время предыдущего обновления в секундах. В зависимости от типа источника (Executable, HTTP, MySQL, PostgreSQL, RT.WideStore , ODBC) к update_field
будет применена соответствующая логика перед запросом данных из внешнего источника.
update_field
будет добавлено в качестве параметра запроса, а время последнего обновления — в качестве значения параметра.update_field
будет добавлено в качестве аргумента исполняемого скрипта, время последнего обновления — в качестве значения аргумента.WHERE
, где update_field
будет больше или равно времени последнего обновления.Если установлена опция update_field
, то может быть установлена дополнительная опция update_lag
. Значение update_lag
вычитается из времени предыдущего обновления перед запросом обновленных данных.
Пример настройки:
<dictionary>
...
<widestore>
...
<update_field>added_time</update_field>
<update_lag>15</update_lag>
</widestore>
...
</dictionary>
или
...
SOURCE(WIDESTORE(... update_field 'added_time' update_lag 15))
...
Внешний словарь можно подключить из множества источников.
Общий вид XML-конфигурации:
<widestore>
<dictionary>
...
<source>
<source_type>
<!-- Source configuration -->
</source_type>
</source>
...
</dictionary>
...
</widestore>
Аналогичный DDL-запрос:
CREATE DICTIONARY dict_name (...)
...
SOURCE(SOURCE_TYPE(param1 val1 ... paramN valN)) -- Source configuration
...
Источник настраивается в разделе source
.
Для типов источников Локальный файл, Исполняемый файл, HTTP(s), RT.WideStore доступны дополнительные настройки:
<source>
<file>
<path>/opt/dictionaries/os.tsv</path>
<format>TabSeparated</format>
</file>
<settings>
<format_csv_allow_single_quotes>0</format_csv_allow_single_quotes>
</settings>
</source>
или
SOURCE(FILE(path './user_files/os.tsv' format 'TabSeparated'))
SETTINGS(format_csv_allow_single_quotes = 0)
Типы источников (source_type
):
Пример настройки:
<source>
<file>
<path>/opt/dictionaries/os.tsv</path>
<format>TabSeparated</format>
</file>
</source>
или
SOURCE(FILE(path './user_files/os.tsv' format 'TabSeparated'))
Поля настройки:
path
— абсолютный путь к файлу.format
— формат файла. Поддерживаются все форматы, описанные в разделе Форматы.Если словарь с источником FILE
создается с помощью DDL-команды (CREATE DICTIONARY ...
), источник словаря должен быть расположен в каталоге user_files
. Иначе пользователи базы данных будут иметь доступ к произвольному файлу на узле RT.WideStore .
Смотрите также:
Работа с исполняемым файлом зависит от размещения словаря в памяти. Если тип размещения словаря cache
и complex_key_cache
, то RT.WideStore запрашивает необходимые ключи, отправляя запрос в STDIN
исполняемого файла.
Пример настройки:
<source>
<executable>
<command>cat /opt/dictionaries/os.tsv</command>
<format>TabSeparated</format>
<implicit_key>false</implicit_key>
</executable>
</source>
Поля настройки:
command
— абсолютный путь к исполняемому файлу или имя файла (если каталог программы прописан в PATH
).format
— формат файла. Поддерживаются все форматы, описанные в разделе Форматы.implicit_key
— исходный исполняемый файл может возвращать только значения, а соответствие запрошенным ключам определено неявно — порядком строк в результате. Значение по умолчанию: false. Необязательный параметр.Этот источник словаря может быть настроен только с помощью XML-конфигурации. Создание словарей с исполняемым источником с помощью DDL запрещено. Иначе пользователь сможет выполнить произвольный бинарный файл на сервере RT.WideStore .
Исполняемый пул позволяет загружать данные из пула процессов. Этот источник не работает со словарями, которые требуют загрузки всех данных из источника. Исполняемый пул работает словарями, которые размещаются следующими способами: cache
, complex_key_cache
, ssd_cache
, complex_key_ssd_cache
, direct
, complex_key_direct
.
Исполняемый пул генерирует пул процессов с помощью указанной команды и оставляет их активными, пока они не завершатся. Программа считывает данные из потока STDIN пока он доступен и выводит результат в поток STDOUT, а затем ожидает следующего блока данных из STDIN. RT.WideStore не закрывает поток STDIN после обработки блока данных и отправляет в него следующую порцию данных, когда это требуется. Исполняемый скрипт должен быть готов к такому способу обработки данных — он должен заранее опрашивать STDIN и отправлять данные в STDOUT.
Пример настройки:
<source>
<executable_pool>
<command><command>while read key; do printf "$key\tData for key $key\n"; done</command</command>
<format>TabSeparated</format>
<pool_size>10</pool_size>
<max_command_execution_time>10<max_command_execution_time>
<implicit_key>false</implicit_key>
</executable_pool>
</source>
Поля настройки:
command
— абсолютный путь к файлу или имя файла (если каталог программы записан в PATH
).format
— формат файла. Поддерживаются все форматы, описанные в “Форматы”.pool_size
— размер пула. Если в поле pool_size
указан 0, то размер пула не ограничен.command_termination_timeout
— скрипт исполняемого пула должен включать основной цикл чтения-записи. После уничтожения словаря канал закрывается. При этом исполняемый файл имеет command_termination_timeout
секунд для завершения работы, прежде чем RT.WideStore пошлет сигнал SIGTERM дочернему процессу. Указывается в секундах. Значение по умолчанию: 10. Необязательный параметр.max_command_execution_time
— максимальное количество времени для исполняемого скрипта на обработку блока данных. Указывается в секундах. Значение по умолчанию: 10. Необязательный параметр.implicit_key
— исходный исполняемый файл может возвращать только значения, а соответствие запрошенным ключам определено неявно — порядком строк в результате. Значение по умолчанию: false. Необязательный параметр.Этот источник словаря может быть настроен только с помощью XML-конфигурации. Создание словарей с исполняемым источником с помощью DDL запрещено. Иначе пользователь сможет выполнить произвольный бинарный файл на сервере RT.WideStore .
Работа с HTTP(s) сервером зависит от размещения словаря в памяти. Если тип размещения словаря cache
и complex_key_cache
, то RT.WideStore запрашивает необходимые ключи, отправляя запрос методом POST
.
Пример настройки:
<source>
<http>
<url>http://[::1]/os.tsv</url>
<format>TabSeparated</format>
<credentials>
<user>user</user>
<password>password</password>
</credentials>
<headers>
<header>
<name>API-KEY</name>
<value>key</value>
</header>
</headers>
</http>
</source>
или
SOURCE(HTTP(
url 'http://[::1]/os.tsv'
format 'TabSeparated'
credentials(user 'user' password 'password')
headers(header(name 'API-KEY' value 'key'))
))
Чтобы RT.WideStore смог обратиться к HTTPS-ресурсу, необходимо настроить openSSL в конфигурации сервера.
Поля настройки:
url
— URL источника.format
— формат файла. Поддерживаются все форматы, описанные в разделе «Форматы».credentials
– базовая HTTP-аутентификация. Необязательный параметр.user
– имя пользователя, необходимое для аутентификации.password
– пароль, необходимый для аутентификации.headers
– все пользовательские записи HTTP-заголовков, используемые для HTTP-запроса. Необязательный параметр.header
– одна запись HTTP-заголовка.name
– идентифицирующее имя, используемое для отправки заголовка запроса.value
– значение, заданное для конкретного идентифицирующего имени.При создании словаря с помощью DDL-команды (CREATE DICTIONARY ...
) удаленные хосты для HTTP-словарей проверяются в разделе remote_url_allow_hosts
из конфигурации сервера. Иначе пользователи базы данных будут иметь доступ к произвольному HTTP-серверу.
Внимание:
При соединении с базой данных через ODBC можно заменить параметр соединения `Servername`.
В этом случае, значения `USERNAME` и `PASSWORD` из `odbc.ini` отправляются на удаленный сервер и могут быть скомпрометированы.
Пример небезопасного использования:
Сконфигурируем unixODBC для работы с PostgreSQL. Содержимое /etc/odbc.ini
:
[gregtest]
Driver = /usr/lib/psqlodbca.so
Servername = localhost
PORT = 5432
DATABASE = test_db
#OPTION = 3
USERNAME = test
PASSWORD = test
Если выполнить запрос вида:
SELECT * FROM odbc('DSN=gregtest;Servername=some-server.com', 'test_db');
то ODBC драйвер отправит значения USERNAME
и PASSWORD
из odbc.ini
на some-server.com
.
ОС Ubuntu.
Установка unixODBC и ODBC-драйвера для PostgreSQL: :
$ sudo apt-get install -y unixodbc odbcinst odbc-postgresql
Настройка /etc/odbc.ini
(или ~/.odbc.ini
):
[DEFAULT]
Driver = myconnection
[myconnection]
Description = PostgreSQL connection to my_db
Driver = PostgreSQL Unicode
Database = my_db
Servername = 127.0.0.1
UserName = username
Password = password
Port = 5432
Protocol = 9.3
ReadOnly = No
RowVersioning = No
ShowSystemTables = No
ConnSettings =
Конфигурация словаря в RT.WideStore:
<widestore>
<dictionary>
<name>table_name</name>
<source>
<odbc>
<!-- в connection_string можно указывать следующие параметры: -->
<!-- DSN=myconnection;UID=username;PWD=password;HOST=127.0.0.1;PORT=5432;DATABASE=my_db -->
<connection_string>DSN=myconnection</connection_string>
<table>postgresql_table</table>
</odbc>
</source>
<lifetime>
<min>300</min>
<max>360</max>
</lifetime>
<layout>
<hashed/>
</layout>
<structure>
<id>
<name>id</name>
</id>
<attribute>
<name>some_column</name>
<type>UInt64</type>
<null_value>0</null_value>
</attribute>
</structure>
</dictionary>
</widestore>
или
CREATE DICTIONARY table_name (
id UInt64,
some_column UInt64 DEFAULT 0
)
PRIMARY KEY id
SOURCE(ODBC(connection_string 'DSN=myconnection' table 'postgresql_table'))
LAYOUT(HASHED())
LIFETIME(MIN 300 MAX 360)
Может понадобиться в odbc.ini
указать полный путь до библиотеки с драйвером DRIVER=/usr/local/lib/psqlodbcw.so
.
ОС Ubuntu.
Установка драйвера:
$ sudo apt-get install tdsodbc freetds-bin sqsh
Настройка драйвера:
$ cat /etc/freetds/freetds.conf
...
[MSSQL]
host = 192.168.56.101
port = 1433
tds version = 7.0
client charset = UTF-8
# тестирование TDS соединения
$ sqsh -S MSSQL -D database -U user -P password
$ cat /etc/odbcinst.ini
[FreeTDS]
Description = FreeTDS
Driver = /usr/lib/x86_64-linux-gnu/odbc/libtdsodbc.so
Setup = /usr/lib/x86_64-linux-gnu/odbc/libtdsS.so
FileUsage = 1
UsageCount = 5
$ cat /etc/odbc.ini
# $ cat ~/.odbc.ini # если вы вошли из под пользователя из под которого запущен widestore[MSSQL]
Description = FreeTDS
Driver = FreeTDS
Servername = MSSQL
Database = test
UID = test
PWD = test
Port = 1433
# (не обязательно) тест ODBC соединения (используйте isql поставляемый вместе с [unixodbc](https://packages.debian.org/sid/unixodbc)-package)
$ isql -v MSSQL "user" "password"
Примечание:
чтобы определить самую раннюю версию TDS, которая поддерживается определенной версией SQL Server, обратитесь к документации продукта или посмотрите на MS-TDS Product Behavior
Настройка словаря в RT.WideStore:
<widestore>
<dictionary>
<name>test</name>
<source>
<odbc>
<table>dict</table>
<connection_string>DSN=MSSQL;UID=test;PWD=test</connection_string>
</odbc>
</source>
<lifetime>
<min>300</min>
<max>360</max>
</lifetime>
<layout>
<flat />
</layout>
<structure>
<id>
<name>k</name>
</id>
<attribute>
<name>s</name>
<type>String</type>
<null_value></null_value>
</attribute>
</structure>
</dictionary>
</widestore>
или
CREATE DICTIONARY test (
k UInt64,
s String DEFAULT ''
)
PRIMARY KEY k
SOURCE(ODBC(table 'dict' connection_string 'DSN=MSSQL;UID=test;PWD=test'))
LAYOUT(FLAT())
LIFETIME(MIN 300 MAX 360)
Этим способом можно подключить любую базу данных, имеющую ODBC драйвер.
Пример настройки:
<source>
<odbc>
<db>DatabaseName</db>
<table>ShemaName.TableName</table>
<connection_string>DSN=some_parameters</connection_string>
<invalidate_query>SQL_QUERY</invalidate_query>
<query>SELECT id, value_1, value_2 FROM ShemaName.TableName</query>
</odbc>
</source>
или
SOURCE(ODBC(
db 'DatabaseName'
table 'SchemaName.TableName'
connection_string 'DSN=some_parameters'
invalidate_query 'SQL_QUERY'
query 'SELECT id, value_1, value_2 FROM db_name.table_name'
))
Поля настройки:
db
— имя базы данных. Не указывать, если имя базы задано в параметрах. <connection_string>
.table
— имя таблицы и схемы, если она есть.connection_string
— строка соединения.invalidate_query
— запрос для проверки статуса словаря. Необязательный параметр. Читайте подробнее в разделе Обновление словарей.query
– пользовательский запрос. Необязательный параметр.ПРИМЕЧАНИЕ:
Поля `table` и `query` не могут быть использованы вместе. Также обязательно должен быть один из источников данных: `table` или `query`.
RT.WideStore получает от ODBC-драйвера информацию о квотировании и квотирует настройки в запросах к драйверу, поэтому имя таблицы нужно указывать в соответствии с регистром имени таблицы в базе данных.
Если у вас есть проблемы с кодировками при использовании Oracle, ознакомьтесь с соответствующим разделом FAQ.
Пример настройки:
<source>
<mysql>
<port>3306</port>
<user>widestore</user>
<password>qwerty</password>
<replica>
<host>example01-1</host>
<priority>1</priority>
</replica>
<replica>
<host>example01-2</host>
<priority>1</priority>
</replica>
<db>db_name</db>
<table>table_name</table>
<where>id=10</where>
<invalidate_query>SQL_QUERY</invalidate_query>
<fail_on_connection_loss>true</fail_on_connection_loss>
<query>SELECT id, value_1, value_2 FROM db_name.table_name</query>
</mysql>
</source>
или
SOURCE(MYSQL(
port 3306
user 'widestore'
password 'qwerty'
replica(host 'example01-1' priority 1)
replica(host 'example01-2' priority 1)
db 'db_name'
table 'table_name'
where 'id=10'
invalidate_query 'SQL_QUERY'
fail_on_connection_loss 'true'
query 'SELECT id, value_1, value_2 FROM db_name.table_name'
))
Поля настройки:
port
— порт сервера MySQL. Можно указать для всех реплик или для каждой в отдельности (внутри <replica>
).
user
— имя пользователя MySQL. Можно указать для всех реплик или для каждой в отдельности (внутри <replica>
).
password
— пароль пользователя MySQL. Можно указать для всех реплик или для каждой в отдельности (внутри <replica>
).
replica
— блок конфигурации реплики. Блоков может быть несколько.
- `replica/host` — хост MySQL.
- `replica/priority` — приоритет реплики. При попытке соединения widestore обходит реплики в соответствии с приоритетом. Чем меньше цифра, тем выше приоритет.
db
— имя базы данных.
table
— имя таблицы.
where
— условие выбора. Синтаксис условия совпадает с синтаксисом секции WHERE
в MySQL, например, id > 10 AND id < 20
. Необязательный параметр.
invalidate_query
— запрос для проверки статуса словаря. Необязательный параметр. Читайте подробнее в разделе Обновление словарей.
fail_on_connection_loss
– параметр конфигурации, контролирующий поведение сервера при потере соединения. Если значение true
, то исключение генерируется сразу же, если соединение между клиентом и сервером было потеряно. Если значение false
, то сервер повторно попытается выполнить запрос три раза прежде чем сгенерировать исключение. Имейте в виду, что повторные попытки могут увеличить время выполнения запроса. Значение по умолчанию: false
.
query
– пользовательский запрос. Необязательный параметр.
ПРИМЕЧАНИЕ:
Поля `table` или `where` не могут быть использованы вместе с полем `query`. Также обязательно должен быть один из источников данных: `table` или `query`.Явный параметр `secure` отсутствует. Автоматически поддержана работа в обоих случаях: когда установка SSL-соединения необходима и когда нет.
MySQL можно подключить на локальном хосте через сокеты, для этого необходимо задать host
и socket
.
Пример настройки:
<source>
<mysql>
<host>localhost</host>
<socket>/path/to/socket/file.sock</socket>
<user>widestore</user>
<password>qwerty</password>
<db>db_name</db>
<table>table_name</table>
<where>id=10</where>
<invalidate_query>SQL_QUERY</invalidate_query>
<fail_on_connection_loss>true</fail_on_connection_loss>
<query>SELECT id, value_1, value_2 FROM db_name.table_name</query>
</mysql>
</source>
или
SOURCE(MYSQL(
host 'localhost'
socket '/path/to/socket/file.sock'
user 'widestore'
password 'qwerty'
db 'db_name'
table 'table_name'
where 'id=10'
invalidate_query 'SQL_QUERY'
fail_on_connection_loss 'true'
query 'SELECT id, value_1, value_2 FROM db_name.table_name'
))
Пример настройки:
<source>
<mongodb>
<host>localhost</host>
<port>27017</port>
<user></user>
<password></password>
<db>test</db>
<collection>dictionary_source</collection>
</mongodb>
</source>
или
SOURCE(MONGODB(
host 'localhost'
port 27017
user ''
password ''
db 'test'
collection 'dictionary_source'
))
Поля настройки:
host
— хост MongoDB.port
— порт сервера MongoDB.user
— имя пользователя MongoDB.password
— пароль пользователя MongoDB.db
— имя базы данных.collection
— имя коллекции.Пример настройки:
<source>
<redis>
<host>localhost</host>
<port>6379</port>
<storage_type>simple</storage_type>
<db_index>0</db_index>
</redis>
</source>
или
SOURCE(REDIS(
host 'localhost'
port 6379
storage_type 'simple'
db_index 0
))
Поля настройки:
host
– хост Redis.port
– порт сервера Redis.storage_type
– способ хранения ключей. Необходимо использовать simple
для источников с одним столбцом ключей, hash_map
– для источников с двумя столбцами ключей. Источники с более, чем двумя столбцами ключей, не поддерживаются. Может отсутствовать, значение по умолчанию simple
.db_index
– номер базы данных. Может отсутствовать, значение по умолчанию 0.Пример настройки:
<source>
<cassandra>
<host>localhost</host>
<port>9042</port>
<user>username</user>
<password>qwerty123</password>
<keyspase>database_name</keyspase>
<column_family>table_name</column_family>
<allow_filering>1</allow_filering>
<partition_key_prefix>1</partition_key_prefix>
<consistency>One</consistency>
<where>"SomeColumn" = 42</where>
<max_threads>8</max_threads>
<query>SELECT id, value_1, value_2 FROM database_name.table_name</query>
</cassandra>
</source>
Поля настройки:
host
– имя хоста с установленной Cassandra или разделенный через запятую список хостов.port
– порт на серверах Cassandra. Если не указан, используется значение по умолчанию: 9042.user
– имя пользователя для соединения с Cassandra.password
– пароль для соединения с Cassandra.keyspace
– имя keyspace (база данных).column_family
– имя семейства столбцов (таблица).allow_filering
– флаг, разрешающий или не разрешающий потенциально дорогостоящие условия на кластеризации ключевых столбцов. Значение по умолчанию: 1.partition_key_prefix
– количество партиций ключевых столбцов в первичном ключе таблицы Cassandra. Необходимо для составления ключей словаря. Порядок ключевых столбцов в определении словаря должен быть таким же, как в Cassandra. Значение по умолчанию: 1 (первый ключевой столбец - это ключ партицирования, остальные ключевые столбцы - ключи кластеризации).consistency
– уровень консистентности. Возможные значения: One
, Two
, Three
, All
, EachQuorum
, Quorum
, LocalQuorum
, LocalOne
, Serial
, LocalSerial
. Значение по умолчанию: One
.where
– опциональный критерий выборки.max_threads
– максимальное количество тредов для загрузки данных из нескольких партиций в словарь.query
– пользовательский запрос. Необязательный параметр.ПРИМЕЧАНИЕ:
Поля `column_family` или `where` не могут быть использованы вместе с полем `query`. Также обязательно должен быть один из источников данных: `column_family` или `query`.
Пример настройки:
<source>
<postgresql>
<port>5432</port>
<user>widestore</user>
<password>qwerty</password>
<db>db_name</db>
<table>table_name</table>
<where>id=10</where>
<invalidate_query>SQL_QUERY</invalidate_query>
<query>SELECT id, value_1, value_2 FROM db_name.table_name</query>
</postgresql>
</source>
или
SOURCE(POSTGRESQL(
port 5432
host 'postgresql-hostname'
user 'postgres_user'
password 'postgres_password'
db 'db_name'
table 'table_name'
replica(host 'example01-1' port 5432 priority 1)
replica(host 'example01-2' port 5432 priority 2)
where 'id=10'
invalidate_query 'SQL_QUERY'
query 'SELECT id, value_1, value_2 FROM db_name.table_name'
))
Поля настройки:
host
– хост для соединения с PostgreSQL. Вы можете указать его для всех реплик или задать индивидуально для каждой релпики (внутри <replica>
).port
– порт для соединения с PostgreSQL. Вы можете указать его для всех реплик или задать индивидуально для каждой релпики (внутри <replica>
).user
– имя пользователя для соединения с PostgreSQL. Вы можете указать его для всех реплик или задать индивидуально для каждой релпики (внутри <replica>
).password
– пароль для пользователя PostgreSQL.replica
– раздел конфигурации реплик. Может быть несколько.replica/host
– хост PostgreSQL.replica/port
– порт PostgreSQL .replica/priority
– приоритет реплики. Во время попытки соединения RT.WideStore будет перебирать реплики в порядке приоритета. Меньшее значение означает более высокий приоритет.db
– имя базы данных.table
– имя таблицы.where
– условие выборки. Синтаксис для условий такой же, как для выражения WHERE
в PostgreSQL. Например, id > 10 AND id < 20
. Необязательный параметр.invalidate_query
– запрос для проверки условия загрузки словаря. Необязательный параметр. Более подробную информацию смотрите в разделе обновление словарей.query
– пользовательский запрос. Необязательный параметр.ПРИМЕЧАНИЕ:
Поля `table` или `where` не могут быть использованы вместе с полем `query`. Также обязательно должен быть один из источников данных: `table` или `query`.
Секция <structure>
описывает ключ словаря и поля, доступные для запросов.
Описание в формате XML:
<dictionary>
<structure>
<id>
<name>Id</name>
</id>
<attribute>
<!-- Attribute parameters -->
</attribute>
...
</structure>
</dictionary>
Атрибуты описываются элементами:
<id>
— столбец с ключом.<attribute>
— столбец данных. Можно задать несколько атрибутов.Создание словаря запросом:
CREATE DICTIONARY dict_name (
Id UInt64,
-- attributes)PRIMARY KEY Id
...
Атрибуты задаются в теле запроса:
PRIMARY KEY
— столбец с ключомAttrName AttrType
— столбец данных. Можно задать несколько столбцов.RT.WideStore поддерживает следующие виды ключей:
UInt64
. Описывается в теге <id>
или ключевым словом PRIMARY KEY
.<key>
или ключевым словом PRIMARY KEY
.Структура может содержать либо <id>
либо <key>
. DDL-запрос может содержать только PRIMARY KEY
.
ОБРАТИТЕ ВНИМАНИЕ:
Ключ не надо дополнительно описывать в атрибутах.
Тип: UInt64
.
Пример конфигурации:
<id>
<name>Id</name>
</id>
Поля конфигурации:
name
— имя столбца с ключами.Для DDL-запроса:
CREATE DICTIONARY (
Id UInt64,
...)
PRIMARY KEY Id
...
PRIMARY KEY
– имя столбца с ключами.Ключом может быть кортеж (tuple
) из полей произвольных типов. В этом случае layout должен быть complex_key_hashed
или complex_key_cache
.
СОВЕТ:
Составной ключ может состоять из одного элемента. Это даёт возможность использовать в качестве ключа, например, строку.
Структура ключа задаётся в элементе <key>
. Поля ключа задаются в том же формате, что и атрибуты словаря. Пример:
<structure>
<key>
<attribute>
<name>field1</name>
<type>String</type>
</attribute>
<attribute>
<name>field2</name>
<type>UInt32</type>
</attribute>
...
</key>
...
или
CREATE DICTIONARY (
field1 String,
field2 String
...
)
PRIMARY KEY field1, field2
...
При запросе в функции dictGet*
в качестве ключа передаётся кортеж. Пример: dictGetString('dict_name', 'attr_name', tuple('string for field1', num_for_field2))
.
Пример конфигурации:
<structure>
...
<attribute>
<name>Name</name>
<type>WideStoreDataType</type>
<null_value></null_value>
<expression>rand64()</expression>
<hierarchical>true</hierarchical>
<injective>true</injective>
<is_object_id>true</is_object_id>
</attribute>
</structure>
или
CREATE DICTIONARY somename (
Name WideStoreDataType DEFAULT '' EXPRESSION rand64() HIERARCHICAL INJECTIVE IS_OBJECT_ID
)
Поля конфигурации:
Тег |
Описание |
Обязательный |
---|---|---|
name | Имя столбца. | Да |
type | Тип данных RT.WideStore : UInt8, UInt16, UInt32, UInt64, Int8, Int16, Int32, Int64, Float32, Float64, UUID, Decimal32, Decimal64, Decimal128, Decimal256, String, Array. RT.WideStore пытается привести значение из словаря к заданному типу данных. Например, в случае MySQL, в таблице-источнике поле может быть TEXT, VARCHAR, BLOB, но загружено может быть как String. Nullable в настоящее время поддерживается для словарей Flat, Hashed, ComplexKeyHashed, Direct, ComplexKeyDirect, RangeHashed, Polygon, Cache, ComplexKeyCache, SSDCache, SSDComplexKeyCache. Для словарей IPTrie Nullable-типы не поддерживаются. |
Да |
null_value | Значение по умолчанию для несуществующего элемента. В примере это пустая строка. Значение NULL можно указывать только для типов Nullable (см. предыдущую строку с описанием типов). |
Да |
expression | Выражение, которое RT.WideStore выполняет со значением. Выражением может быть имя столбца в удаленной SQL базе. Таким образом, вы можете использовать его для создания псевдонима удаленного столбца. Значение по умолчанию: нет выражения. |
Нет |
hierarchical | Если true, то атрибут содержит ключ предка для текущего элемента. Смотрите Иерархические словари. Значение по умолчанию: false. |
Нет |
is_object_id | Признак того, что запрос выполняется к документу MongoDB по ObjectID. Значение по умолчанию: false. |
Нет |
Смотрите также:
Функции для работы с внешними словарями.
RT.WideStore поддерживает иерархические словари с числовыми ключом.
Рассмотрим следующую структуру:
0 (Common parent)
│
├── 1 (Russia)
│ │
│ └── 2 (Moscow)
│ │
│ └── 3 (Center)
│└── 4 (Great Britain)
│
└── 5 (London)
Эту иерархию можно выразить в виде следующей таблицы-словаря.
region_id |
parent_region |
region_name |
---|---|---|
1 | 0 | Russia |
2 | 1 | Moscow |
3 | 2 | Center |
4 | 0 | Great Britain |
5 | 4 | London |
Таблица содержит столбец parent_region
, содержащий ключ ближайшего предка для текущего элемента.
RT.WideStore поддерживает свойство hierarchical для атрибутов внешнего словаря. Это свойство позволяет конфигурировать словари, подобные описанному выше.
С помощью функции dictGetHierarchy можно получить цепочку предков элемента.
Структура словаря для нашего примера может выглядеть следующим образом:
<dictionary>
<structure>
<id>
<name>region_id</name>
</id>
<attribute>
<name>parent_region</name>
<type>UInt64</type>
<null_value>0</null_value>
<hierarchical>true</hierarchical>
</attribute>
<attribute>
<name>region_name</name>
<type>String</type>
<null_value></null_value>
</attribute>
</structure>
</dictionary>
Словари полигонов позволяют эффективно искать полигон, в который попадают данные точки, среди множества полигонов. Для примера: определение района города по географическим координатам.
Пример конфигурации словаря полигонов:
<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>
<store_polygon_key_column>1</store_polygon_key_column>
</polygon>
</layout>
...
</dictionary>
Соответствующий DDL-запрос:
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))
...
При конфигурации словаря полигонов ключ должен иметь один из двух типов:
Точки могут задаваться массивом или кортежем из своих координат. В текущей реализации поддерживаются только двумерные точки.
Пользователь может загружать свои собственные данные во всех поддерживаемых RT.WideStore форматах.
Доступно 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 = TinyLog;
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(WIDESTORE(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 │
└────────────────────────────────────┴────────┘
RT.WideStore содержит встроенную возможность работы с геобазой.
Это позволяет:
Все функции поддерживают «транслокальность», то есть возможность использовать одновременно разные точки зрения на принадлежность регионов. Подробнее смотрите в разделе «Функции для работы со словарями Яндекс.Метрики».
В пакете по умолчанию, встроенные словари выключены. Для включения, раскомментируйте параметры path_to_regions_hierarchy_file
и path_to_regions_names_files
в конфигурационном файле сервера.
Геобаза загружается из текстовых файлов.
Положите файлы regions_hierarchy*.txt
в директорию path_to_regions_hierarchy_file
. Этот конфигурационный параметр должен содержать путь к файлу regions_hierarchy.txt
(иерархия регионов по умолчанию), а другие файлы (regions_hierarchy_ua.txt
) должны находиться рядом в той же директории.
Положите файлы regions_names_*.txt
в директорию path_to_regions_names_files
.
Также вы можете создать эти файлы самостоятельно. Формат файлов такой:
regions_hierarchy*.txt
: TabSeparated (без заголовка), столбцы:
идентификатор региона (UInt32);
UInt32
);UInt8
): 1 - континент, 3 - страна, 4 - федеральный округ, 5 - область, 6 - город; остальные типы не имеют значения;UInt32
) - не обязательный столбец.regions_names_*.txt
: TabSeparated (без заголовка), столбцы:
UInt32
);String
) - не может содержать табы или переводы строк, даже экранированные.Для хранения в оперативке используется плоский массив. Поэтому, идентификаторы не должны быть больше миллиона.
Словари могут обновляться без перезапуска сервера. Но набор доступных словарей не обновляется. Для обновления проверяется время модификации файлов; если файл изменился, то словарь будет обновлён. Периодичность проверки настраивается конфигурационным параметром builtin_dictionaries_reload_interval
. Обновление словарей (кроме загрузки при первом использовании) не блокирует запросы - во время обновления запросы используют старую версию словарей. Если при обновлении возникнет ошибка, то ошибка пишется в лог сервера, а запросы продолжат использовать старую версию словарей.
Рекомендуется периодически обновлять словари с геобазой. При обновлении, генерируйте новые файлы, записывая их в отдельное место, а только когда всё готово - переименовывайте в файлы, которые использует сервер.
Также имеются функции для работы с идентификаторами операционных систем и поисковых систем Яндекс.Метрики, пользоваться которыми не нужно.