Обновляемые материализованные представления и другие функции ClickHouse Release 23.12.
3 января 2024 г.Новогодний выпуск ClickHouse
Новая версия ClickHouse была выпущена в декабре 2023 года. Давайте посмотрим, какие интересные новые функции есть внутри, и погрузимся в одну из них — новые обновляемые материализованные представления!
Что изображено на доске?
Этот выпуск содержит 21 новую функцию, 18 оптимизаций производительности и 37 исправлений ошибок.
Вот несколько интересных функций, о которых я хотел бы вам сообщить:
- Новые обновляемые материализованные представления. Он создает обновляемые представления, подобные crontab.
- Новое предложение PASTE JOIN. Удобное соединение наборов данных по строкам 1:1.
- Новое предложение ORDER BY ALL. Синтаксический сахар для упорядочивания запроса по каждому столбцу из оператора SELECT.
- Новая команда мутации ALTER TABLE
APPLY DELETED MASK. Он применяет маску, написанную методом упрощенного удаления, для удаления с диска строк, помеченных как удаленные.
- Возможность ссылаться на столбец ALIAS в определениях индекса (не первичного ключа).
Полный список изменений вы можете прочитать здесь.
А пока я покажу пример использования материализованных представлений.
Обновляемые материализованные представления
ClickHouse периодически запускает соответствующий запрос и сохраняет его результат в таблице, атомарно заменяя предыдущее содержимое таблицы, что принципиально отличается от обычных необновляемых материализованных представлений: не инкрементальный, а полный пересчет и переформатирование данных из исходных таблиц.
Конечно, есть компромиссы: его больше нет в сети, а это затраты на агрегирующие запросы. Необновляемые материализованные представления ограничены использованием функций агрегирования в запросе, поскольку они применяются только к инкрементальным данным. Для запроса SELECT нет никаких ограничений. Разрешены табличные функции (например, url()), представления, UNION, JOIN.
Поскольку эта функция является экспериментальной, ее необходимо включить, установив
SET allow_experimental_refreshable_materialized_view = 1
Давайте создадим своего рода синтетический пример: сканер обходит URL-адреса в одном домене с помощью DFS и сохраняет заголовки запросов, заголовки ответов и контент в простой таблице.
CREATE TABLE IF NOT EXISTS crawler.pages (
url String,
req_headers Map(String, String),
resp_headers Map(String, String),
resp_code Int,
content String,
links Nested (
uri String,
titles Array(String)
)
)
ENGINE MergeTree
PRIMARY KEY url
ORDER BY url
Эта новая функция позволяет мне создавать удобные конвейеры. Следующий пример довольно синтетический, однако он демонстрирует
Исходная («исходная») таблица может содержать дубликаты для любой страницы, поэтому первым шагом обработки данных будет выбор уникальных страниц с дополнительным условием: непустой заголовок ответа etag и код ответа 200 с использованием преобразования данных, такого как извлечение домена. и анализ даты сканирования.
CREATE MATERIALIZED VIEW IF NOT EXISTS crawler.uniqpages
REFRESH EVERY 2 MINUTE --- refresh could be SECOND|MINUTE|HOUR|DAY|WEEK|MONTH|YEAR
RANDOMIZE FOR 1 MINUTE
ENGINE = Memory
AS SELECT DISTINCT
domainWithoutWWW(url) as domain, -- extract domain from the url builtin func
path(url) as uri, -- extract path from the url builtin func
url as url,
resp_headers['etag'] as etag,
parseDateTime32BestEffort(resp_headers['date']) as crawled_at, -- datetime parsing
req_headers['user-agent'] as user_agent,
resp_code as resp_code,
links.uri as nei_uris,
links.titles as nei_titles
FROM
crawler.pages
WHERE
resp_headers['etag'] <> '' AND resp_code = 200
Второй шаг — предварительный расчет уникальной достоверной статистики страниц для каждого домена. Этот шаг будет зависеть от завершения обновления представления uniqpages, без этой зависимости они оба запускаются одновременно.
CREATE MATERIALIZED VIEW IF NOT EXISTS crawler.stats
REFRESH EVERY 2 MINUTE
DEPENDS ON crawler.uniqpages -- sync with uniqpages view, this ensures refresh to run in sequence
ENGINE = Memory
AS SELECT DISTINCT
domain,
count(1) as qnt
FROM
crawler.uniqpages
GROUP BY
1
ORDER BY
ALL
Проверьте uniqpages
на наличие записей, чтобы проверить результаты.
dd4a5ae26651 :) select * from uniqpages limit 1 format Vertical
SELECT *
FROM uniqpages
LIMIT 1
FORMAT Vertical
Query id: ba19be7b-0891-4c07-a707-62e5e3eaa3c4
Row 1:
──────
domain: levelup.gitconnected.com
uri: /%EF%B8%8F-how-to-deploy-a-static-website-or-a-server-side-rendered-app-with-aws-amplify-hosting-806b4d620458
url: https://levelup.gitconnected.com/%EF%B8%8F-how-to-deploy-a-static-website-or-a-server-side-rendered-app-with-aws-amplify-hosting-806b4d620458?source=---------4-----------------------
etag: W/"1c8ed-8WUFxf2KDh2sBbP4zrGTJCdxo4I"
crawled_at: 2023-12-31 14:20:54
user_agent: Mozilla/5.0 (X11; Linux x86_64; Testbot/1.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36
resp_code: 200
nei_uris: ['https://levelup.gitconnected.com/?source=post_page-----806b4d620458--------------------------------']
nei_titles: [['Level Up Coding','Level Up Coding']]
1 row in set. Elapsed: 0.001 sec. Processed 22.91 thousand rows, 209.44 MB (30.17 million rows/s., 275.83 GB/s.)
Peak memory usage: 15.02 KiB.
Давайте проверим статистику
dd4a5ae26651 :) select domain, qnt from stats order by domain
SELECT
domain,
qnt
FROM stats
ORDER BY domain ASC
Query id: 9a2975ea-b52a-44ec-acae-698bb51f1973
┌─domain───────────────────┬───qnt─┐
│ habr.com │ 12941 │
│ levelup.gitconnected.com │ 9295 │
│ w3.org │ 665 │
│ wikipedia.org │ 6 │
└──────────────────────────┴───────┘
4 rows in set. Elapsed: 0.001 sec.
… и через пару минут
dd4a5ae26651 :) select domain, qnt from stats order by domain
SELECT
domain,
qnt
FROM stats
ORDER BY domain ASC
Query id: 9a2975ea-b52a-44ec-acae-698bb51f1973
┌─domain───────────────────┬───qnt─┐
│ habr.com │ 12947 │
│ levelup.gitconnected.com │ 9316 │
│ w3.org │ 665 │
│ wikipedia.org │ 6 │
└──────────────────────────┴───────┘
4 rows in set. Elapsed: 0.001 sec.
Заключение
Обновляемое материализованное представление — очень удобная и самая интересная функция этой версии. Это позволяет мне очень просто создавать полезные конвейеры ETL данных, используя SQL, позволяя ClickHouse выполнять рутинную работу за вас.
Дайте мне знать в комментариях, какая из новых функций вас больше всего волнует!
Оригинал