Как стать автором
Обновить
2
0
Отправить сообщение

Ну так, тогда и наняли безопасников.
Пять лет кормили этих дармоедов, а подобных инцидентов не происходило, вот и решили срезать косты.

Проблема в том, что dynamic reconfiguration не позволяет "прозрачно" передать лидера, так что ее наличие к сожалению не решает нашу главную проблему: незаметно для ClickHouse перенести кластер ZooKeeper. В любом случае будет временная потеря кворума и наша задача сделать так, что бы это минимальным образом отразилось на времени простоя ClickHouse для вставок.

Так что тот план можно использовать и для миграций старших версий ZooKeeper.

Есть хорошее руководство, не раз опробованное на практике, по миграции ZooKeeper который используется для ClickHouse.

Остановили запись, посчитали число ивентов, которые там лежат за день. Закинули еще данных, от которых не записалась только треть. Три шарды по 2 реплики. Вставляешь 100.000 строк — 33.000 не записываются.

Звучит как какая то магия, вам кликхаус что возвращал после вставки? OK?
Кликхаус умеет тихо скипать вставки если они побайтно идентичны, не похоже ли это на ваши «вставляешь 100к строк, а 33к не записываются»?

Наличие двух разных независимых кластеров и пайплайнов данных это в принципе достаточно разумная схема.
Функции высшего порядка — особенностью этих функций является невозможность вызова функции внутри функции. То есть нельзя напрямую использовать, скажем, функцию arrayMap в качестве аргумента функции arrayFilter.

Строго говоря это не так, никто не мешает наслаивать их друг на друга.
SELECT arrayMap(x -> (x + 2), arrayFilter((x, y) -> (x = y), [1, 2, 3], [1, 3, 3])) AS res

┌─res───┐
│ [3,5] │
└───────┘

SELECT arrayMap(x -> arrayAll(s -> (s = 1), x), [[1, 1, 1], [1, 2, 3], [3], [1]]) AS res

┌─res───────┐
│ [1,0,0,1] │
└───────────┘

SELECT arrayFilter(x -> (arraySum(y -> (y % 2), x) > 4), [[1, 2, 3, 4], [2, 4, 6, 8, 10], [1, 3, 5, 7, 9]]) AS res

┌─res───────────┐
│ [[1,3,5,7,9]] │
└───────────────┘
SELECT arrayFilter(x -> (arrayReduce('sum', arrayMap(y -> (y % 2), x)) > 4), [[1, 2, 3, 4], [2, 4, 6, 8, 10], [1, 3, 5, 7, 9]]) AS res

┌─res───────────┐
│ [[1,3,5,7,9]] │
└───────────────┘
Если кратко: будет выигрывать и за счет всего.
Для увеличения шансов postgresql можно добавить еще timescaledb extention, но он не сильно поможет.
А если отвечать серьезно, то за счет сжатия данных, параллельном исполнении запросов, поколоночном хранении данных, удобном партицировании.

Но речь конечно идет о тех нагрузках, под которые оптимизирован clickhouse: относительно редкие запросы которые затрагивают сразу большой объем данных.
Дергать значения по ключу скорее всего postgresql будет быстрее.
SELECT count(*)
FROM
(
SELECT
person,
sequenceCount('(?1).*(?2).*(?3)')(toDateTime(when), zone = 0, zone = 3, zone = 19) AS c
FROM steps
WHERE area = 0 and zone IN (0,3,19) --ну если мы отсекаем ненужные зоны в запросе с join то можем и тут их не сканировать.
GROUP BY person
)
WHERE c > 0

В чем проблема клика с JOIN?
В том, что тк в клихаусе индекс разряженный, кликхаус использует merge джоин и ему приходится поднимать правую таблицу в оперативную память и сортировать ее, что обязательно выстрелит в ногу, когда у тебя в правой таблице окажется сотни миллионов — миллиарды записей. Поэтому в кликхаусе желательно избегать JOIN, на небольших правых таблицах можно обходится словарями.
Кликхаус конечно не тормозит, но почему было решено сделать подобные запросы через INNER JOIN(N^2), вместо GROUP BY user и дальше через массивы и лямбдами(arrayMap,arrayFilter,arrayReduce), либо через то подмножество оконных функций в кликхаусе, что уже есть. Это было бы в тысячи раз быстрее на больших датасетах.
CREATE TABLE logs
(
....
)
  ENGINE = MergeTree()
  PARTITION BY (date, toHour(timestamp))
  ORDER BY (timestamp, nsec,namespace, container_name)
  TTL date + toIntervalDay(14)
  SETTINGS index_granularity = 32768;

Почасовые партиции?
Сложно угадать сколько у вас в среднем падает логов ежедневно, но можно допустить что несколько сотен лямов в день, а с таким кол-вом можно спокойной жить и с партициями по месяцу.
Но учитывая ваш TTL подневные может вам и сойдут, но даже они далеко не всем нужны.
ORDER BY (timestamp, nsec, namespace, container_name)
Сомнительный ORDER BY, вообще по всем канонам в начало ORDER BY идут те поля, которые учавствуют в подавляющем большинстве запросов, что бы отбрасывать ненужные нам гранулы. С вашим ORDER BY так не выйдет.
timestamp и date вполне можно объединить в 1 столбец, тогда для партицирования использовать toYYYYMMDD(timestamp).
А для особенно смелых, можно использовать DateTime64, тогда и nsec можно там хранить.
Еще не видно никаких Codecs, они могут очень значительно повлиять на объем хранимых данных.
count(*)
Звездочка в count() ненужна, возможно может даже негативно влиять на скорость сканирования.

Вообще я бы в вашем случае попробовал, что то вроде
ORDER BY (namespace, container_name,timestamp, nsec)
И возможно, задал бы PRIMARY KEY покороче, допустим (namespace, container_name,timestamp)
накидаю парочку ~подобных игр
garry's mod из интересного программирование хоть на компонентах, хоть на языке lua
From the Depths что то вроде майна с постройкой кораблей/ЛА и пвп
factorio постройка цепочек производства, не совсем похоже, но все равно затягивает
Не зря вы вспомнили про медицину, ей есть что предложить по теме
Наигрались

Информация

В рейтинге
Не участвует
Зарегистрирован
Активность