Обновляемые материализованные представления и другие функции ClickHouse Release 23.12.

Обновляемые материализованные представления и другие функции 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 выполнять рутинную работу за вас.

Дайте мне знать в комментариях, какая из новых функций вас больше всего волнует!


Оригинал
PREVIOUS ARTICLE
NEXT ARTICLE