Pull to refresh
95
0
Алексей @o6CuFl2Q

Разработчик

Send message

Недавно как раз писал статью о том, как мы боремся с флапающими тестами: https://clickhouse.com/blog/en/2021/tests-visualization/

Самое большое различие в количестве для названия "счетчик".
Причина в том, что MySQL агрегирует без учёта диакритики:
http://sqlfiddle.com/#!9/0a28f18/584
(выполняет некоторую нормализацию перед агрегацией)


Можно написать так:


SELECT BINARY name, count(*) FROM conv_main.counters GROUP BY BINARY name ORDER BY count(*) DESC LIMIT 10;

Правда так запрос в MySQL только сильно замедляется (уже выполняется 20 минут и я не могу дождаться). Может быть надо CAST(... AS VARBINARY) или что-то типа того.


Различия в работе clickhouse-local на примере в статье, по сравнению с sort, uniq в следующем:


  1. LC_ALL=C
  2. В clickhouse-local не указан формат входных данных. По-умолчанию используется TabSeparated (TSV). Он предусматривает экранирование. В том числе, можно экранировать перевод строки с помощью бэкслеша. В коде на C++ бэкслеш в конце строки тоже попадается — в экранировании макросов. Таким образом, в clickhouse-local некоторые строки (у которых бэкслеш на конце), превратятся в одну. Получить в точности такой же результат можно, указав формат LineAsString:

milovidov@milovidov-desktop:~/work/ClickHouse$ find {src,programs,utils,base} -name '*.h' -or -name '*.cpp' | grep -v generated | xargs cat > code.txt

milovidov@milovidov-desktop:~/work/ClickHouse$ time LC_ALL=C cat code.txt | sed -r -e 's/^ +//' | grep . | sort | uniq -c | sort -rn | head -n10
  57004 {
  52665 }
   6277 };
   4708 else
   3422 namespace DB
   2705 public:
   2277 */
   2268 return false;
   2142 break;
   1858 #pragma once

real    0m2,051s
user    0m2,244s
sys     0m0,139s

milovidov@milovidov-desktop:~/work/ClickHouse$ time clickhouse-local --input-format 'LineAsString' --structure 's String' --query "SELECT count() AS c, trimLeft(s) AS key FROM table WHERE key != '' GROUP BY key ORDER BY c DESC LIMIT 10" < code.txt
57004   {
52665   }
6277    };
4708    else
3422    namespace DB
2705    public:
2277    */
2268    return false;
2142    break;
1858    #pragma once

real    0m0,186s
user    0m0,150s
sys     0m0,037s

Да, запросы делались в разное время (но не сильно разное — наверное в течение часа) на продакшен базе.


Я попробую сейчас сделать пару похожих запросов и выясню, в чём различия.

Такого вида оптимизации вполне имеют практический смысл. Например, в ClickHouse похожим образом сделана функция formatDateTime:


https://github.com/ClickHouse/ClickHouse/blob/master/src/Functions/formatDateTime.cpp#L54

Спасибо за такой подробный обзор, наконец-то удалось что-то понять!
Сейчас пробуем добавить -fstrict-vtable-pointers, -fwhole-program-vtables при сборке Clickhouse:
https://github.com/ClickHouse/ClickHouse/pull/20151


Но что-то пошло не так и lld-11 упал при линковке (из-за LTO): https://clickhouse-builds.s3.yandex.net/20151/7b3481322edb4ed1f0f1f76128c3283d87fd4fbf/clickhouse_build_check/build_log_889491481_1612624311.txt

Почти всё правильно написано.


Если при вставке затронуто несколько партиций, то вставка в каждую из них атомарна по отдельности, но не весь INSERT в целом.


max_insert_block_size по-умолчанию 1 млн. строк, если вставка меньше, то она разбивается на несколько. Настройку max_insert_block_size можно менять по своему усмотрению.


min_insert_block_size_rows, min_insert_block_size_bytes не влияют на атомарность, тут Denny Crane ошибся.


Если на таблицу навешаны материализованные представления, то вставка в таблицу, по прежнему, атомарна, как и вставки во все связанные таблицы, но все эти вставки вместе не являются атомарной операцией.

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


Один вариант — проверять доступность хотя бы одной из существующих реплик при создании новой реплики. То есть, что новая реплика сможет скачать хоть какие-то данные с существующих.


Этот вариант не подходит по двум причинам:


  • добавление новой реплики при временной недоступности старой — полностью легальный сценарий;
  • это не защитит от ошибки, когда реплики всё-таки доступны по сети, но новая реплика добавляется по ошибке.

Второй вариант — сделать новую форму запросов CREATE REPLICA, и сделать так, что CREATE TABLE будет только соглашаться создавать новую таблицу, а не новую реплику существующей таблицы. Но это поломает обратную совместимость. Или сделать форму запроса CREATE TABLE… FIRST REPLICA, которая будет проверять то же самое. Вроде уже лучше. Но непонятно, насколько внесение изменений в язык запросов соотносится с тем, будут ли это широко использовать.


Третий вариант — это выводить логи в клиент при создании таблицы. В логах уже написано — первая ли это реплика или новая реплика, которая будет клонировать существующую. И эти логи можно получить, выставив send_logs_level. Остаётся только включить вывод каких-то вариантов логов на клиент по-умолчанию и рассчитывать на то, что их прочитают.


Четвёртый вариант — при создании новой реплики, возвращать результат CREATE TABLE только после того, как новая реплика синхронизировалась. Этот вариант тоже отменяется, так как синхронизация часто бывает долгой (дни). Делать для этой опции отдельную настройку тоже нецелесообразно, так как её мало кто будет использовать.

По состоянию на 2020, ClickHouse — непревзойдённое решение на таком сценарии.
Рекомендую посмотреть статью — демо работы ClickHouse на одном сервере на данных событий GitHub: gh.clickhouse.tech/explorer

Там же можно нажать на карандашик и повыполнять разные запросы в реальном времени.
> поддерживается только JOIN с подзапросом в качестве правой части;

Теперь поддерживаются не только такие виды JOIN.

> условия в join-е не пробрасываются внутрь подзапроса;

Теперь пробрасываются. (За исключением некоторых случаев — например, в правую часть LEFT JOIN).

> распределённые join-ы выполняются неэффективно.

В некоторой мере осталось так же.
Наверное на машине мало оперативки, хотя часть результатов можно добавить.
This method:
base64 < /dev/urandom | head -c8
Вот тут выложены презентации для почти всех работ за прошлый год: github.com/yandex/clickhouse-presentations/tree/master/hse_2019
Яндекс Метрика довольно популярна в Европе и соответствует европейским законам. Можно изучить все детали тут: metrica.yandex.com/about — внизу в разделе Legal.

Information

Rating
Does not participate
Location
Россия
Works in
Registered
Activity