Как проверить недавно не просмотренные данные с помощью материализованного представления в Clickhouse

Я получил эти таблицы

  • seen_ids таблица с идентификаторами.
  • source_ids таблица нулевого движка, куда поступают данные
  • target_ids со свежими идентификаторами, которых не было в увиденном_ids на момент его появления.

Мне нужно хранить только идентификаторы, которых нет в увиденных_идах:

    CREATE materialized view mv_fresh
    TO target_ids
    AS SELECT
      *
    FROM source_ids where id not in (select id from seen_ids)

Также Id добавляется к seen_ids, поэтому в следующий раз он не будет добавлен к target_ids.

Другой вариант — использовать LEFT JOIN, но, возможно, для большой таблицы это тоже не лучшая идея.

Это пример того, что мне нужно сделать. Какие способы вы рекомендуете проверить на идентификаторы «недавно не видели»? Этот пример, вероятно, плохой дизайн для большой таблицы seen_ids (50 миллионов строк) и больших данных о доходах.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
61
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Несколько способов улучшить производительность:

  1. попробуйте оптимизировать оператор IN
CREATE materialized view mv_fresh
    TO target_ids
    AS SELECT
     ..
    FROM source_ids
    where id not in (
        select id from seen_ids 
        where id IN (select id FROM source_ids))
  1. рассмотрите возможность уменьшения index_granularity для db.seen_ids или использования пропуска индексов

См. Индексы пропуска: установите.

CREATE TABLE db.seen_ids_local ON CLUSTER cl
(..)
ORDER BY id
ENGINE = MergeTree()
SETTINGS index_granularity = 256 or 512 or ..;
  1. попытайтесь найти некоторую информацию о данных, которая поможет уменьшить объем обрабатываемых данных

Например, если id является инкрементальным, то можно применить некоторое условие WHERE id > {some_value_that_calculated_by_MV}

  1. использовать движок SET

Имеет смысл рассмотреть возможность использования таблицы с движком SET для хранения просмотренных идентификаторов и использования их в операторе IN.

  1. массовая вставка (тысячи строк и более)

Это необходимо

  • либо измените логику сервиса, записывающего данные в db.source_ids
  • или используйте Buffer engine (см. соответствующие вопросы на SO)
  1. использовать распределенное вычисление (шардинг) (разделить идентификаторы на группы, которые выполняются независимо)

Например, для 2 шардов на каждом необходимо выполнить 50 / 2 = 25 mln ряды seen_ids таблицы.

CREATE TABLE db.seen_ids_local ON CLUSTER cl
(..)
ORDER BY id
ENGINE = MergeTree();

/* ! Write data to distributed table to reshard them among shards. Or write data directly to shard based on sharding key. */
CREATE TABLE db.seen_ids ON CLUSTER cl AS db.seen_ids_local
ENGINE = Distributed(cl, db, seen_ids_local, intHash32(id)); /* Reshard data by 'id'. */


CREATE TABLE db.source_ids_local ON CLUSTER cl
(..)
ENGINE = Null;

/* ! Write data to distributed table to reshard them among shards. */
CREATE TABLE db.source_ids ON CLUSTER cl AS db.source_ids_local
ENGINE = Distributed(cl, db, source_ids_local, intHash32(id)); /* Reshard data by 'id'. The same sharding key as for 'seen_ids' */


CREATE TABLE db.target_ids_local ON CLUSTER cl
(..)
ENGINE = MergeTree();

CREATE materialized view db.target_ids_local_mv
TO db.target_ids_local  /* [Optional] Write data to local table */
AS SELECT
..  
FROM db.source_ids_local /* !! Load data from local table */
where id not in (
  select id from db.seen_ids_local /* !! Load data from local table */
)

Посмотрите эти документы: База знаний Altinity.

Большое спасибо, я попробую разные способы и надеюсь обновить вопрос своими показателями.

Егор Лебедев 31.05.2024 08:52

Другие вопросы по теме