InfluxDB — это популярная база данных временных рядов, и я здесь, чтобы показать вам, как ее запрашивать. Он использует SQL-подобный (или, если честно, «почти-SQL») язык.
|
1
|
SELECT * FROM "foodships" WHERE time > now() - 1h |
Этот язык работает и поддерживается в InfluxDB с первого дня, и у него есть как плюсы, так и минусы:
- Новым пользователям легко взаимодействовать с базой данных на языке, который они уже знают. SQL популярен, и многие разработчики уже знают его. Этот синтаксис запросов помог InfluxDB расти в первые дни.
- Как я уже говорил, InfluxQL — это язык «amost-SQL». Написание языка SQL-запросов не простая работа. Одна из проблем заключается в том, что администраторы баз данных имеют некоторые ожидания от SQL, но наш язык не полностью совместим с SQL. Это создает много несоответствий и сомнений .
- Одной из характеристик базы данных временных рядов является то, что запись не может блокировать чтение, а чтение не может блокировать запись. Это необходимая вещь. Ваши устройства IOT или ваши серверы всегда будут записывать метрики, а ваша панель мониторинга, аналитические инструменты и менеджеры предупреждений будут считывать данные из базы данных. InfluxDB нужно что-то более масштабируемое.
- На данный момент механизм хранения и язык запросов находятся в одном проекте, который блокирует быструю итерацию кода, который мы хотели бы иметь. Язык запросов развивается намного быстрее по сравнению с механизмом хранения. Движок нуждается в стабильности, но язык запросов нуждается в большем количестве функций и возможностей.
- InfluxQL нуждается в ре-архитектуре, потому что команда не смогла реализовать все удивительные идеи, требуемые сообществом.
- В настоящее время SQL очень прост в изучении, но в нашем стеке есть еще один DSL-доступ: скрипт TICK, используемый Kapacitor для отправки предупреждений и уменьшения количества ваших серий.
- InfluxQL не имеет математических функций, потому что язык не позволяет нам добавлять их простым способом. С IFQL их будет очень легко реализовать.
Во время InfluxDays в Сан-Франциско Пол Дикс , технический директор и основатель InfluxData, выпустил на сцену новый язык запросов с открытым исходным кодом, чтобы приблизить анализ данных к InfluxDB. Это называется IFQL .
Архитектура
|
1
2
3
4
5
6
7
8
|
var cpu = select(db: "telegraf") .filter(exp:{"_measurement" == "cpu" and "_field" == "usage_user"}) .range(start: -30m) select(db: "telegraf") .filter(exp:{"_measurement" == "mem" and "_field" == "used_percent"}) .range(start: -30m) .join(on:["host"], eval:{$ + cpu}) |
IFQL — это не просто язык запросов. У него есть синтаксический анализатор, который читает запрос, подобный приведенному выше, и генерирует план, который можно визуализировать как JSON и запускать напрямую через IFQL. Это означает, что синтаксис, который вы видите, является лишь одной из возможных реализаций. Настоящий контракт заключается между планом и обработчиком.
Архитектура и идея проекта позволят нам переопределить InfluxQL и PromQL, TICK Script поверх IFQL AST. Кроме того, если у вас есть построитель запросов или вам необходимо создать собственную реализацию для взаимодействия с InfluxDB, вы можете сгенерировать план в виде простого JSON и передать его в IFQL. Гибкая и удивительная.
IFQL предназначен для расширения и достижения этой цели — мы извлекли важный урок из Telegraf. Вам нужен чистый интерфейс и единственная точка входа, чтобы разработчики с удовольствием внесли свой вклад в ваш проект. Вот почему у IFQL есть каталог /functions . Он содержит все функции, поддерживаемые в настоящее время, и участники, желающие добавить функции, должны работать только в этом каталоге.
TICK Script и IFQL
Одна из целей IFQL — предоставить все возможности, которые в настоящее время предоставляет TICK Script, чтобы мы могли запрашивать, обрабатывать и отправлять оповещения, не изучая два языка.
В настоящее время у нас есть функции, реплицированные в обоих проектах, но мы сможем повторно использовать их с IFQL.
На данный момент IFQL является отдельным проектом, доступным на GitHub . Помимо анализатора и планировщика, он предоставляет простой http-демон с именем ifqld для запуска некоторых тестов.
Он находится в бета-версии, что означает, что API и синтаксис запросов изменятся, но его очень легко настроить. Я буду использовать Docker для этого примера, но вы можете найти здесь исполняемые файлы IFQL, deb и rpm, если вы не знаете Docker.
Давайте загрузим файл конфигурации InfluxDB из репозитория IFQL:
|
1
2
3
|
wget https://raw.githubusercontent.com/influxdata/ifql/master/docker-compose.ymlmkdir exampleswget https://raw.githubusercontent.com/influxdata/ifql/master/examples/influxdb.conf -O examples/influxdb.conf |
Основным отличием является параграф, который включает IFQL:
|
1
2
3
4
|
[ifql] enabled = true log-enabled = true bind-address = ":8082" |
InfluxDB использует порт 8082 для запуска связи gRPC с IFQL.
|
1
|
docker-compose up |
Как видите, мы создали сеть и развернули два контейнера. Одним из них является InfluxDB с нашей модифицированной конфигурацией и открытыми 8082 и 8086. Второй — IFQL v0.0.2. Он предоставляет порт 8093, и мы можем проверить, что все работает как положено, запустив простой curl:
|
1
2
3
4
5
6
|
15:21 $ curl -I http://localhost:8093/HTTP/1.1 404 Not FoundContent-Type: text/plain; charset=utf-8X-Content-Type-Options: nosniffDate: Tue, 28 Nov 2017 14:21:40 GMTContent-Length: 19 |
Теперь давайте заполним нашу базу данных некоторыми примерами данных:
|
01
02
03
04
05
06
07
08
09
10
|
influx -import -path=NOAA_data.txt -precision=s -database=NOAA_water_databaseinfluxuse NOAA_water_databaseSELECT COUNT(*) FROM NOAA_water_database> SELECT COUNT(*) FROM h2o_feetname: h2o_feettime count_level description count_water_level---- ----------------------- -----------------0 15258 15258 |
Как видите, у нас есть несколько точек и измерений. Теперь мы будем взаимодействовать с ifqld используя curl чтобы запустить несколько основных примеров:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
20:11 $ curl -XPOST --data-urlencode 'q=from(db:"NOAA_water_database").filter(exp:{"_measurement"=="h2o_temperature"}).range(start: -500000h).limit(n: 10)' http://localhost:8093/query h2o_temperature,location=coyote_creek degrees=60 1439856000000000000 h2o_temperature,location=coyote_creek degrees=65 1439856360000000000 h2o_temperature,location=coyote_creek degrees=68 1439856720000000000 h2o_temperature,location=coyote_creek degrees=62 1439857080000000000 h2o_temperature,location=coyote_creek degrees=62 1439857440000000000 h2o_temperature,location=coyote_creek degrees=69 1439857800000000000 h2o_temperature,location=coyote_creek degrees=67 1439858160000000000 h2o_temperature,location=coyote_creek degrees=67 1439858520000000000 h2o_temperature,location=coyote_creek degrees=70 1439858880000000000 h2o_temperature,location=coyote_creek degrees=65 1439859240000000000 h2o_temperature,location=santa_monica degrees=70 1439856000000000000 h2o_temperature,location=santa_monica degrees=60 1439856360000000000 h2o_temperature,location=santa_monica degrees=62 1439856720000000000 h2o_temperature,location=santa_monica degrees=62 1439857080000000000 h2o_temperature,location=santa_monica degrees=60 1439857440000000000 h2o_temperature,location=santa_monica degrees=63 1439857800000000000 h2o_temperature,location=santa_monica degrees=64 1439858160000000000 h2o_temperature,location=santa_monica degrees=63 1439858520000000000 h2o_temperature,location=santa_monica degrees=63 1439858880000000000 h2o_temperature,location=santa_monica degrees=61 1439859240000000000 |
Давайте сравним ранжированный запрос from(db:"NOAA_water_database").filter(exp:{"_measurement"=="h2o_temperature"}).range(start:
-500000h).limit(n: 10)from(db:"NOAA_water_database").filter(exp:{"_measurement"=="h2o_temperature"}).range(start:
-500000h).limit(n: 10)from(db:"NOAA_water_database").filter(exp:{"_measurement"=="h2o_temperature"}).range(start: с InfluxQL:
-500000h).limit(n: 10)
-
fromработает немного похоже наselectв SQL. Он выбираетdatabaseдля запроса. -
filterна стероидах. Вы можете фильтровать поtagsиспользуя операторы, такие как<,>,==и!=. - Внутри
filterесть некоторые конкретные ключевые слова, такие как_measurementиспользуемые самой базой данных. В этом случае он фильтруется по измерениюh2o_temperature. -
limit(10)возвращает 20 строк в этом случае. Что здесь происходит? Это одно из первых различий в том, как мы создали язык запросов. Существует неявнаяgroup by *которая группируется по серии. В этом случае есть две серии:h2o_temperature,location=santa_monicaиh2o_temperature,location=coyote_creek. Если вам нужна конкретная серия, вы должны добавить.filter(exp:{"_measurement"=="h2o_temperature" AND "location" ==
"coyote_creek"}).filter(exp:{"_measurement"=="h2o_temperature" AND "location" ==
"coyote_creek"}).filter(exp:{"_measurement"=="h2o_temperature" AND "location" ==.
"coyote_creek"})
Некоторые важные решения, лежащие в основе языка запросов:
- Порядок аргументов для функции не важен. Каждый аргумент имеет имя и не является обязательным.
- Используйте
"везде», чтобы избежать несоответствия между одинарными и двойными кавычками.
IFQL упрощает каждый запрос от определенного синтаксиса до JSON AST. Вы можете получить AST для вашего конкретного запроса, добавив запрос param analyze=true .
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
19:56 $ curl -s -XPOST --data-urlencode 'q=from(db:"NOAA_water_database").range(start: 200h).count()' http://localhost:8093/query?analyze=true | jq{ "operations": [ { "id": "from0", "kind": "from", "spec": { "database": "NOAA_water_database", "hosts": null } }, { "id": "range1", "kind": "range", "spec": { "start": "200h0m0s", "stop": "now" } }, { "id": "count2", "kind": "count", "spec": {} } ], "edges": [ { "parent": "from0", "child": "range1" }, { "parent": "range1", "child": "count2" } ]} |
README.md внутри проекта IFQL документирует все остальные доступные функции.
Зарегистрируй бесплатный аккаунт Codeship
Масштабируемость
ifqld является демоном HTTP без сохранения состояния, поэтому его можно масштабировать проще и проще, чем InfluxDB (или другие базы данных), поскольку в нем нет данных о состоянии или данных. Некоторые функции, такие как filters , передаются механизму (не во всех случаях), поскольку InfluxDB может извлекать временные ряды и все необходимые точки.
Другие функции, такие как функции агрегирования, не передаются в InfluxDB, а запускаются процессом ifqld как только он возвращает данные из базы данных. Это позволяет нам более гибко масштабировать чтение и агрегацию. В случае большего количества запросов или большего количества требований к вычислениям мы можем ifqld больше процессов ifqld не заботясь об основном хранилище.
Другим важным аспектом масштабируемости является то, что ifqld может запрашивать более одного influxdb .
|
1
2
3
4
5
6
7
8
|
00:04 $ ./bin/ifqld --helpUsage: ifqld [OPTIONS]Options for the IFQLD serverApplication Options: -h, --host= influx hosts to query from. Can be specified more than once for multiple hosts. (default: localhost:8082) [$HOSTS] |
Используя аргумент CLI --host= или переменную среды $HOSTS вы можете указать более одного бэкэнда. Это означает, что если вы работаете с версией с открытым исходным кодом и можете управлять разделением данных поверх большего количества баз данных, вы можете сортировать данные по горизонтали.
Дорожная карта
Проект нестабилен и быстро развивается. API и результаты могут меняться в зависимости от вашего опыта работы с языком запросов. Идея состоит в том, чтобы заблокировать API в начале 2018 года. Если вы являетесь активным пользователем InfluxDB, попробуйте его и не стесняйтесь открывать PR или сообщать о своем сценарии использования, чтобы помочь нам улучшить синтаксис.
| Опубликовано на Java Code Geeks с разрешения Джанлуки Арбеццано, партнера нашей программы JCG. Смотрите оригинальную статью здесь: Как сделать запрос InfluxDB
Мнения, высказанные участниками Java Code Geeks, являются их собственными. |