mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-19 14:11:58 +00:00
67c2e50331
* update presentations * CLICKHOUSE-2936: redirect from clickhouse.yandex.ru and clickhouse.yandex.com * update submodule * lost files * CLICKHOUSE-2981: prefer sphinx docs over original reference * CLICKHOUSE-2981: docs styles more similar to main website + add flags to switch language links * update presentations * Less confusing directory structure (docs -> doc/reference/) * Minify sphinx docs too * Website release script: fail fast + pass docker hash on deploy * Do not underline links in docs * shorter * cleanup docker images * tune nginx config * CLICKHOUSE-3043: get rid of habrastorage links * Lost translation * CLICKHOUSE-2936: temporary client-side redirect * behaves weird in test * put redirect back * CLICKHOUSE-3047: copy docs txts to public too * move to proper file * remove old pages to avoid confusion * Remove reference redirect warning for now * Refresh README.md * Yellow buttons in docs * Use svg flags instead of unicode ones in docs * fix test website instance * Put flags to separate files * wrong flag * Copy Yandex.Metrica introduction from main page to docs * Yet another home page structure change, couple new blocks (CLICKHOUSE-3045) * Update Contacts section * CLICKHOUSE-2849: more detailed legal information * CLICKHOUSE-2978 preparation - split by files * More changes in Contacts block * Tune texts on index page * update presentations * One more benchmark * Add usage sections to index page, adapted from slides * Get the roadmap started, based on slides from last ClickHouse Meetup * CLICKHOUSE-2977: some rendering tuning * Get rid of excessive section in the end of getting started * Make headers linkable * CLICKHOUSE-2981: links to editing reference - https://github.com/yandex/ClickHouse/issues/849 * CLICKHOUSE-2981: fix mobile styles in docs * Ban crawling of duplicating docs * Open some external links in new tab * Ban old docs too * Lots of trivial fixes in english docs * Lots of trivial fixes in russian docs * Remove getting started copies in markdown * Add Yandex.Webmaster * Fix some sphinx warnings * More warnings fixed in english docs * More sphinx warnings fixed * Add code-block:: text * More code-block:: text * These headers look not that well * Better switch between documentation languages * merge use_case.rst into ya_metrika_task.rst * Edit the agg_functions.rst texts * Add lost empty lines * Lost blank lines * Add new logo sizes * update presentations * Next step in migrating to new documentation * Fix all warnings in en reference * Fix all warnings in ru reference * Re-arrange existing reference * Move operation tips to main reference * Fix typos noticed by milovidov@ * Get rid of zookeeper.md * Looks like duplicate of tutorial.html * Fix some mess with html tags in tutorial * No idea why nobody noticed this before, but it was completely not clear whet to get the data * Match code block styling between main and tutorial pages (in favor of the latter) * Get rid of some copypaste in tutorial * Normalize header styles * Move example_datasets to sphinx * Move presentations submodule to website * Move and update README.md * No point in duplicating articles from habrahabr here * Move development-related docs as is for now * doc/reference/ -> docs/ (to match the URL on website) * Adapt links to match the previous commit * Adapt development docs to rst (still lacks translation and strikethrough support) * clean on release * blacklist presentations in gulp * strikethrough support in sphinx * just copy development folder for now * fix weird introduction in style article * Style guide translation (WIP) * Finish style guide translation to English * gulp clean separately * Update year in LICENSE * Initial CONTRIBUTING.md * Fix remaining links to old docs in tutorial * Some tutorial fixes * Typo * Another typo * Update list of authors from yandex-team accoding to git log
347 lines
26 KiB
ReStructuredText
347 lines
26 KiB
ReStructuredText
Внешние словари
|
||
===============
|
||
|
||
Существует возможность подключать свои собственные словари из различных источников данных.
|
||
Источником данных для словаря может быть файл на локальной файловой системе, сервер ClickHouse, сервер MySQL, MongoDB или любой ODBC источник.
|
||
Словарь может полностью храниться в оперативке и периодически обновляться, или быть частично закэшированным в оперативке и динамически подгружать отсутствующие значения.
|
||
|
||
Конфигурация внешних словарей находится в отдельном файле или файлах, указанных в конфигурационном параметре dictionaries_config.
|
||
Этот параметр содержит абсолютный или относительный путь к файлу с конфигурацией словарей. Относительный путь - относительно директории с конфигурационным файлом сервера. Путь может содержать wildcard-ы \* и ? - тогда рассматриваются все подходящие файлы. Пример: dictionaries/\*.xml.
|
||
|
||
Конфигурация словарей, а также множество файлов с конфигурацией, может обновляться без перезапуска сервера. Сервер проверяет обновления каждые 5 секунд. То есть, словари могут подключаться динамически.
|
||
|
||
Создание словарей может производиться при старте сервера или при первом использовании. Это определяется конфигурационном параметром dictionaries_lazy_load (в основном конфигурационном файле сервера). Параметр не обязателен, по умолчанию - true. Если true, то каждый словарь создаётся при первом использовании; если словарь не удалось создать - вызов функции, использующей словарь, кидает исключение. Если false, то все словари создаются при старте сервера, и в случае ошибки, сервер завершает работу.
|
||
|
||
Конфигурационный файл словарей имеет вид:
|
||
|
||
.. code-block:: xml
|
||
|
||
<dictionaries>
|
||
<comment>Не обязательный элемент с любым содержимым; полностью игнорируется.</comment>
|
||
|
||
<!-- Можно задать произвольное количество разных словарей. -->
|
||
<dictionary>
|
||
<!-- Имя словаря. Под этим именем словарь будет доступен для использования. -->
|
||
<name>os</name>
|
||
|
||
<!-- Источник данных. -->
|
||
<source>
|
||
|
||
<!-- Источник - файл на локальной файловой системе. -->
|
||
<file>
|
||
<!-- Путь на локальной файловой системе. -->
|
||
<path>/opt/dictionaries/os.tsv</path>
|
||
<!-- С помощью какого формата понимать файл. -->
|
||
<format>TabSeparated</format>
|
||
</file>
|
||
|
||
<!-- или источник - таблица на сервере MySQL.
|
||
<mysql>
|
||
<!- - Эти параметры могут быть указаны как снаружи (общие для всех реплик), так и внутри конкретной реплики - ->
|
||
<port>3306</port>
|
||
<user>clickhouse</user>
|
||
<password>qwerty</password>
|
||
<!- - Можно указать от одной до произвольного количества реплик для отказоустойчивости. - ->
|
||
<replica>
|
||
<host>example01-1</host>
|
||
<priority>1</priority> <!- - Меньше значение - больше приоритет. - ->
|
||
</replica>
|
||
<replica>
|
||
<host>example01-2</host>
|
||
<priority>1</priority>
|
||
</replica>
|
||
<db>conv_main</db>
|
||
<table>counters</table>
|
||
</mysql>
|
||
-->
|
||
|
||
<!-- или источник - таблица на сервере ClickHouse.
|
||
<clickhouse>
|
||
<host>example01-01-1</host>
|
||
<port>9000</port>
|
||
<user>default</user>
|
||
<password></password>
|
||
<db>default</db>
|
||
<table>counters</table>
|
||
</clickhouse>
|
||
<!- - Если адрес похож на localhost, то запрос будет идти без сетевого взаимодействия.
|
||
Для отказоустойчивости, вы можете создать Distributed таблицу на localhost и прописать её. - ->
|
||
-->
|
||
|
||
<!-- Для <mysql> и <clickhouse> доступен атрибут <where>, позволяющий задать условие выбора
|
||
<clickhouse>
|
||
<host>example01-01-1</host>
|
||
<port>9000</port>
|
||
<user>default</user>
|
||
<password></password>
|
||
<db>default</db>
|
||
<table>ids</table>
|
||
<where>id=10</where>
|
||
</clickhouse>
|
||
-->
|
||
|
||
<!-- или источник - исполняемый файл. Если layout.cache - список нужных ключей будет записан в поток STDIN программы -->
|
||
<executable>
|
||
<!-- Путь или имя программы (если директория есть в переменной окружения PATH) и параметры -->
|
||
<command>cat /opt/dictionaries/os.tsv</command>
|
||
<!-- С помощью какого формата понимать вывод и формировать список ключей. -->
|
||
<format>TabSeparated</format>
|
||
</executable>
|
||
|
||
<!-- или источник - http сервер. Если layout.cache - список нужных ключей будет послан как POST запрос -->
|
||
<http>
|
||
<url>http://[::1]/os.tsv</url>
|
||
<!-- С помощью какого формата понимать ответ и формировать список ключей. -->
|
||
<format>TabSeparated</format>
|
||
</http>
|
||
|
||
</source>
|
||
|
||
<!-- Периодичность обновления для полностью загружаемых словарей. 0 - никогда не обновлять. -->
|
||
<lifetime>
|
||
<min>300</min>
|
||
<max>360</max>
|
||
<!-- Периодичность обновления выбирается равномерно-случайно между min и max,
|
||
чтобы размазать по времени нагрузку при обновлении словарей на большом количестве серверов. -->
|
||
</lifetime>
|
||
|
||
<!-- или
|
||
<!- - Периодичность обновления для полностью загружаемых словарей или время инвалидации для кэшируемых словарей.
|
||
0 - никогда не обновлять. - ->
|
||
<lifetime>300</lifetime>
|
||
-->
|
||
|
||
<layout> <!-- Способ размещения в памяти. -->
|
||
<flat />
|
||
<!-- или
|
||
<hashed />
|
||
или
|
||
<cache>
|
||
<!- - Размер кэша в количестве ячеек; округляется вверх до степени двух. - ->
|
||
<size_in_cells>1000000000</size_in_cells>
|
||
</cache>
|
||
-->
|
||
</layout>
|
||
|
||
<!-- Структура. -->
|
||
<structure>
|
||
<!-- Описание столбца, являющегося идентификатором (ключом) словаря. -->
|
||
<id>
|
||
<!-- Имя столбца с идентификатором. -->
|
||
<name>Id</name>
|
||
</id>
|
||
|
||
<attribute> <!-- id уже входит в атрибуты и дополнительно указывать его здесь не нужно. -->
|
||
<!-- Имя столбца. -->
|
||
<name>Name</name>
|
||
<!-- Тип столбца. (Как столбец понимается при загрузке.
|
||
В случае MySQL, в таблице может быть TEXT, VARCHAR, BLOB, но загружается всё как String) -->
|
||
<type>String</type>
|
||
<!-- Какое значение использовать для несуществующего элемента. В примере - пустая строка. -->
|
||
<null_value></null_value>
|
||
</attribute>
|
||
|
||
<!-- Может быть указано произвольное количество атрибутов. -->
|
||
<attribute>
|
||
<name>ParentID</name>
|
||
<type>UInt64</type>
|
||
<null_value>0</null_value>
|
||
<!-- Определяет ли иерархию - отображение в идентификатор родителя (по умолчанию, false). -->
|
||
<hierarchical>true</hierarchical>
|
||
<!-- Можно считать отображение id -> attribute инъективным, чтобы оптимизировать GROUP BY. (по умолчанию, false) -->
|
||
<injective>true</injective>
|
||
</attribute>
|
||
|
||
<!-- Атрибут может быть выражением -->
|
||
<attribute>
|
||
<name>expr</name>
|
||
<type>UInt64</type>
|
||
<expression>rand64()</expression>
|
||
<null_value>0</null_value>
|
||
</attribute>
|
||
</structure>
|
||
</dictionary>
|
||
</dictionaries>
|
||
|
||
Идентификатор (ключевой атрибут) словаря должен быть числом, помещающимся в UInt64.
|
||
Также есть возможность задавать произвольные составные ключи (см. раздел "Словари с составными ключами"). Замечание: составной ключ может состоять и из одного элемента, что даёт возможность использовать в качестве ключа, например, строку.
|
||
|
||
|
||
Существует шесть способов размещения словаря в памяти.
|
||
|
||
flat
|
||
----
|
||
В виде плоских массивов. Самый эффективный способ. Он подходит, если все ключи меньше 500 000. Если при создании словаря обнаружен ключ больше, то кидается исключение и словарь не создаётся. Словарь загружается в оперативку целиком. Словарь использует количество оперативки, пропорциональное максимальному значению ключа. Ввиду ограничения на 500 000, потребление оперативки вряд ли может быть большим.
|
||
Поддерживаются все виды источников. При обновлении, данные (из файла, из таблицы) читаются целиком.
|
||
|
||
hashed
|
||
------
|
||
В виде хэш-таблиц. Слегка менее эффективный способ. Словарь тоже загружается в оперативку целиком, и может содержать произвольное количество элементов с произвольными идентификаторами. На практике, имеет смысл использовать до десятков миллионов элементов, пока хватает оперативки.
|
||
Поддерживаются все виды источников. При обновлении, данные (из файла, из таблицы) читаются целиком.
|
||
|
||
cache
|
||
-----
|
||
Наименее эффективный способ. Подходит, если словарь не помещается в оперативку. Представляет собой кэш из фиксированного количества ячеек, в которых могут быть расположены часто используемые данные. Поддерживается источник MySQL, ClickHouse, executable, http; источник-файл не поддерживается. При поиске в словаре, сначала просматривается кэш. На каждый блок данных, все не найденные в кэше ключи (или устаревшие ключи) собираются в пачку, и с этой пачкой делается запрос к источнику вида SELECT attrs... FROM db.table WHERE id IN (k1, k2, ...). Затем полученные данные записываются в кэш.
|
||
|
||
range_hashed
|
||
------------
|
||
В таблице прописаны какие-то данные для диапазонов дат, для каждого ключа. Дать возможность доставать эти данные для заданного ключа, для заданной даты.
|
||
|
||
|
||
Пример: таблица содержит скидки для каждого рекламодателя в виде:
|
||
.. code-block:: text
|
||
|
||
.. code-block:: text
|
||
|
||
+------------------+-----------------------------+------------+----------+
|
||
| id рекламодателя | дата начала действия скидки | дата конца | величина |
|
||
+==================+=============================+============+==========+
|
||
| 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 |
|
||
+------------------+-----------------------------+------------+----------+
|
||
|
||
Добавляем ``layout = range_hashed``.
|
||
При использовании такого layout, в structure должны быть элементы ``range_min``, ``range_max``.
|
||
|
||
Пример:
|
||
|
||
.. code-block:: xml
|
||
|
||
<structure>
|
||
<id>
|
||
<name>Id</name>
|
||
</id>
|
||
<range_min>
|
||
<name>first</name>
|
||
</range_min>
|
||
<range_max>
|
||
<name>last</name>
|
||
</range_max>
|
||
...
|
||
|
||
Эти столбцы должны иметь тип Date. Другие типы пока не поддерживаем.
|
||
Столбцы обозначают закрытый диапазон дат.
|
||
|
||
Для работы с такими словарями, функции dictGetT должны принимать ещё один аргумент - дату:
|
||
|
||
``dictGetT('dict_name', 'attr_name', id, date)``
|
||
|
||
Функция достаёт значение для данного id и для диапазона дат, в который входит переданная дата. Если не найден id или для найденного id не найден диапазон, то возвращается значение по умолчанию для словаря.
|
||
|
||
Если есть перекрывающиеся диапазоны, то можно использовать любой подходящий.
|
||
|
||
Если граница диапазона является NULL или является некорректной датой (1900-01-01, 2039-01-01), то диапазон следует считать открытым. Диапазон может быть открытым с обеих сторон.
|
||
|
||
В оперативке данные представлены в виде хэш-таблицы со значением в виде упорядоченного массива диапазонов и соответствующих им значений.
|
||
|
||
Пример словаря по диапазонам:
|
||
|
||
.. code-block:: xml
|
||
|
||
<dictionaries>
|
||
<dictionary>
|
||
<name>xxx</name>
|
||
<source>
|
||
<mysql>
|
||
<password>xxx</password>
|
||
<port>3306</port>
|
||
<user>xxx</user>
|
||
<replica>
|
||
<host>xxx</host>
|
||
<priority>1</priority>
|
||
</replica>
|
||
<db>dicts</db>
|
||
<table>xxx</table>
|
||
</mysql>
|
||
</source>
|
||
<lifetime>
|
||
<min>300</min>
|
||
<max>360</max>
|
||
</lifetime>
|
||
<layout>
|
||
<range_hashed />
|
||
</layout>
|
||
<structure>
|
||
<id>
|
||
<name>Abcdef</name>
|
||
</id>
|
||
<range_min>
|
||
<name>StartDate</name>
|
||
</range_min>
|
||
<range_max>
|
||
<name>EndDate</name>
|
||
</range_max>
|
||
<attribute>
|
||
<name>XXXType</name>
|
||
<type>String</type>
|
||
<null_value />
|
||
</attribute>
|
||
</structure>
|
||
</dictionary>
|
||
</dictionaries>
|
||
|
||
complex_key_hashed
|
||
------------------
|
||
|
||
Для использования с составными ключами. Аналогичен hashed.
|
||
|
||
complex_key_cache
|
||
-----------------
|
||
|
||
Для использования с составными ключами. Аналогичен cache.
|
||
|
||
Примечания
|
||
----------
|
||
|
||
Рекомендуется использовать способ ``flat``, если возможно, или ``hashed``, ``complex_key_hashed``. Скорость работы словарей с таким размещением в памяти является безупречной.
|
||
|
||
Способы ``cache`` и ``complex_key_cache`` следует использовать лишь если это неизбежно. Скорость работы кэша очень сильно зависит от правильности настройки и сценария использования. Словарь типа cache нормально работает лишь при достаточно больших hit rate-ах (рекомендуется 99% и выше). Посмотреть средний hit rate можно в таблице system.dictionaries. Укажите достаточно большой размер кэша. Количество ячеек следует подобрать экспериментальным путём - выставить некоторое значение, с помощью запроса добиться полной заполненности кэша, посмотреть на потребление оперативки (эта информация находится в таблице system.dictionaries); затем пропорционально увеличить количество ячеек так, чтобы расходовалось разумное количество оперативки. В качестве источника для кэша рекомендуется MySQL, MongoDB, так как ClickHouse плохо обрабатывает запросы со случайными чтениями.
|
||
|
||
Во всех случаях, производительность будет выше, если вызывать функцию для работы со словарём после ``GROUP BY``, или если доставаемый атрибут помечен как инъективный. Для cache словарей, производительность будет лучше, если вызывать функцию после LIMIT-а - для этого можно использовать подзапрос с LIMIT-ом, и снаружи вызывать функцию со словарём.
|
||
|
||
Атрибут называется инъективным, если разным ключам соответствуют разные значения атрибута. Тогда при использовании в ``GROUP BY`` функции, достающей значение атрибута по ключу, эта функция автоматически выносится из GROUP BY.
|
||
|
||
При обновлении словарей из файла, сначала проверяется время модификации файла, и загрузка производится только если файл изменился.
|
||
При обновлении из MySQL, для flat и hashed словарей, сначала делается запрос ``SHOW TABLE STATUS`` и смотрится время обновления таблицы. И если оно не NULL, то оно сравнивается с запомненным временем. Это работает для MyISAM таблиц, а для InnoDB таблиц время обновления неизвестно, поэтому загрузка из InnoDB делается при каждом обновлении.
|
||
|
||
Для cache-словарей может быть задано время устаревания (``lifetime``) данных в кэше. Если от загрузки данных в ячейке прошло больше времени, чем lifetime, то значение не используется, и будет запрошено заново при следующей необходимости его использовать.
|
||
|
||
Если словарь не удалось ни разу загрузить, то при попытке его использования, будет брошено исключение.
|
||
Если при запросе к источнику cached словаря возникла ошибка, то будет брошено исключение.
|
||
Обновление словарей (кроме загрузки при первом использовании) не блокирует запросы - во время обновления используется старая версия словаря. Если при обновлении возникнет ошибка, то ошибка пишется в лог сервера, а запросы продолжат использовать старую версию словарей.
|
||
|
||
Список внешних словарей и их статус можно посмотреть в таблице ``system.dictionaries``.
|
||
|
||
Для использования внешних словарей, смотрите раздел "Функции для работы с внешними словарями".
|
||
|
||
Обратите внимание, что вы можете преобразовать значения по небольшому словарю, указав всё содержимое словаря прямо в запросе SELECT - смотрите раздел "Функция transform". Эта функциональность никак не связана с внешними словарями.
|
||
|
||
Словари с составными ключами
|
||
----------------------------
|
||
|
||
В качестве ключа может выступать кортеж (tuple) из полей произвольных типов. Параметр layout в этом случае должен быть равен complex_key_hashed или complex_key_cache.
|
||
|
||
Структура ключа задаётся не в элементе ``<id>``, а в элементе ``<key>``. Поля ключа задаются в том же формате, что и атрибуты словаря. Пример:
|
||
|
||
.. code-block:: xml
|
||
|
||
<structure>
|
||
<key>
|
||
<attribute>
|
||
<name>field1</name>
|
||
<type>String</type>
|
||
</attribute>
|
||
<attribute>
|
||
<name>field2</name>
|
||
<type>UInt32</type>
|
||
</attribute>
|
||
...
|
||
</key>
|
||
...
|
||
|
||
|
||
При использовании такого словаря, в функции dictGet* в качестве ключа передаётся Tuple со значениями полей. Пример: ``dictGetString('dict_name', 'attr_name', tuple('field1', 123))``.
|