
Denis
24.08.2018
13:23:22
альтернатива - увеличить max_insert_block_size временно

Александр
24.08.2018
13:24:53
разбить так, чтобы файл был меньше блока. а там он уж либо напишет ошибку, либо вставится. те, что не вставились - вставить заново.
У нас на запись может отправиться 4 сотни файлов, которые заполняются безконтрольно ( Перезаписывать их так, что бы они влезали в max_insert_block_size тоже никак. И опять таки, остается вопрос как вот исходя из этого определить что дописалось, а что нет?
cat 6.t 1.t 2.t 3.t 4.t 5.t | clickhouse-client -q 'INSERT INTO t12345 FORMAT TSV'
Code: 27. DB::Exception: Cannot parse input: expected \n before: afa\n5\n: (at row 10000004)
Row 10000003:
Column 0, name: Number, type: UInt64, parsed text: "3"
Row 10000004:
Column 0, name: Number, type: UInt64, ERROR: text "afa<LINE FEED>5<LINE FEED>" is not like UInt64
По факту записался файл 6.t и то, не полный, а все остальные пролетели мимо

Denis
24.08.2018
13:25:45
отправлять файлы на запись по очереди, конечно

Google

Александр
24.08.2018
13:25:48
Даже если я побью их на размер < max_insert_block_size проблема остается актуальной, т.к. КХ все равно из всего потока данных будет собирать блоки в max_insert_block_size
В файле может быть 1 строка, а может быть 1000...а КХ нужно пачками их кормить и большими
Вставляем это все через cat ... | clickhouse-client

Denis
24.08.2018
13:26:31
возможно, стоит написать какое-нибудь буферное приложение, которое бы делало ретраи. ксати, это идея

Александр
24.08.2018
13:27:07
Что бы писалось либо все, либо ничего

Denis
24.08.2018
13:28:03
а точно нет варианта регулировать размер файлов? ограничить по max_insert_block_size ?
тогда ретраить проще будет гораздо. и файлы всё-таки по одному кидать,

Michal
24.08.2018
13:28:43

Александр
24.08.2018
13:29:01

Denis
24.08.2018
13:29:38
двойная работа получается

Александр
24.08.2018
13:30:02

Google

Александр
24.08.2018
13:30:09
Долго, но блин...
Другого варианта пока нет (

Michal
24.08.2018
13:30:57
двойная работа получается
угу. В принципе можно ATTACH / DETACH чтоб избежать двойной работы. Но тогда надо будет ещё и файлах базы КХ ковыряться.

Александр
24.08.2018
13:33:15
@milovidov_an не планируется что-то типа такого функционала добавлять?
Ситуация: есть много файлов с данными, которые превышают max_insert_block_size и соответственно CH бьет это дело на разные блоки в соответствии с этой настройкой. И вот у меня данных на 3 блока, один блок вставился на в середине второго блока нашлась ошибка в данных и запрос упал. В CH осталась первый блок данных, но мне нужно: либо записалось все, либо ничего. Как такого можно достичь? Кто-то сталкивался с подобной потребностью?
Может быть уже есть?

Michal
24.08.2018
13:34:47
Ну и кстати линуксовего split никто не отменял.

Александр
24.08.2018
13:37:10
@mfilimonov ^^
А это бесмысленно.
Например у меня max_insert_block_size = 1024
Первый файл у меня 200 байт
Второй 150
Третий 2048
В итоге у меня первый блок захватит первый файл, второй и часть третьего, оставшуюся часть третьего он побъет еще на два блока.
Я все равно не узнаю какой файл отвалился
И строки не фиксированной длинны

Michal
24.08.2018
13:40:17
Это ж линукс. Можно сделать так: сначала всем файлам добавить имя файла в начале каждой строки. Потом всё это скормить сплиту (он умеет "резать" по макс размеру, не только по количеству строк). Полученными файлами можно кормить КХ.
Тогда в начале строки будет стоять название оригинального файла.
Правда это всё звучит как-то ээээ ... слишком экзотично :)
Проще починить файлы чтоб инсерты не ломались :)


Konstantin
24.08.2018
13:42:34
коллеги, подскажите. С переходом с версии с 385 на 18.10.3 отвалился драйвер odbc к psql. до этого стоял и работал без проблем. в логи КХ падает такое:
2018.08.24 13:36:03.651668 [ 12 ] <Error> ExternalDictionaries: Failed reloading 'advertisers' external dictionary: Poco::Exception. Code: 1000, e.code() = 0, e.displayText() = Connection attempt failed: Connection:Not applicable
Server:DBNAME
===========================
ODBC Diagnostic record #1:
===========================
SQLSTATE = 01000
Native Error Code = 0
[unixODBC][Driver Manager]Can't open lib 'psqlodbcw.so' : file not found
, e.what() = Connection attempt failed
Хотя сам файл psqlodbcw.so есть. Посмотрел по чейнжлогам - вроде ничего не меняли в работе с ODBC. кто нить сталкивался с такой петрушкой?

Michal
24.08.2018
13:44:19

Александр
24.08.2018
13:46:13
А по диску как? Просто мы с синтетической нагрузкой и всякими мерджами файлов и пр диск жрем на 100% и начинается веселье. Нагрузка порядка 2 000 000 пользователей в сутки
И нам лишние операции на диске боком вылезают

Michal
24.08.2018
13:46:53

Google

Александр
24.08.2018
13:47:01
В плане подготовки данных для отправки в кх, можно конечно это ограничивать, но может забиваться все это дело

Michal
24.08.2018
13:48:19

Александр
24.08.2018
13:49:12
Ща гляну

Michal
24.08.2018
13:50:48
Но он там только форматирование CSV поправлял чтоб КХ все понимал. Т.е. только косметические изменения - типа кавычкек, бекслешей и т.п.

Konstantin
24.08.2018
13:55:06

Denis
24.08.2018
13:56:21
Кстати...отличная идея!
мы все льем через временные tinylog или memory, max_insert_block_size и max_block_size выставляем по кол-ву строк во временной.

Александр
24.08.2018
14:01:40

Denis
24.08.2018
14:01:59
в строках

Александр
24.08.2018
14:02:42
в строках
А льете по http? Просто мы используем clickhouse-client, а он сам бьет данные на блоки

Denis
24.08.2018
14:04:26
только clickhouse-client. Цель атомарность, мне как раз не надо бить на блоки.
tsv -> clickhouse-client -> memory_table (clickhouse-client insert select) -> mergetree
---
max_block_size - это рекомендация, какого размера блоки (в количестве строк) загружать из таблицы.
https://clickhouse.yandex/docs/ru/operations/settings/settings/#max_block_size
--
выставлять надо оба параметра, для insert select

Александр
24.08.2018
14:09:11

Kirill
24.08.2018
14:18:36


Denis
24.08.2018
14:58:27
max_insert_block_size для вставки с клиента,
max_block_size для insert into t select .. from
for i in seq 1 20000000; do echo $i; done > x.tsv
echo xxx >> x.tsv
for i in seq 1 2000; do echo $i; done >> x.tsv
drop table i;
create table i(a Int64) ENGINE=MergeTree PARTITION by tuple() order by tuple();
cat x.tsv |clickhouse-client --max_insert_block_size 30000000 -q 'insert into i format TSV'
Code: 27. DB::Exception: Cannot parse input.....
select count() from i;
0 rows in set. Elapsed: 0.001 sec.


Alexey
24.08.2018
15:13:22
Инструкция №3
—————————————————————
Как настроить TCP балансировку ClickHouse.
В случае если ваше приложение обращается к ClickHouse не через http 8123, а tcp 9000, настроить балансировку ClickHouse серверов используя Nginx просто так не получится. Нужно пересобрать Nginx из исходного кода, указав большое количество нужных параметров, так как в стандартном билде nginx не умеет работать с tcp трафиком. А собрать нужный вариант nginx'a дело не быстрое и лучше не тратьте на это время...
Есть намного более простой и быстрый способ, далее команды под рутом:
1) yum install haproxy -y
2) systemctl enable haproxy
3) systemctl start haproxy
4) vi /etc/haproxy/haproxy.cfg
5) запишем в этот файл:
global
user haproxy
group haproxy
daemon
maxconn 50000
defaults
mode tcp
balance leastconn
timeout client 30000ms
timeout server 30000ms
timeout connect 3000ms
retries 0
frontend from
bind 0.0.0.0:9000
default_backend to
backend to
server srv1 192.168.1.151:9000 maxconn 20000
server srv2 192.168.1.152:9000 maxconn 20000
6) Сохраним файл и выйдем из него
7) systemctl restart haproxy
8) Готово
Примечание 1:
Проверял на Centos 7.5.1804 (4.18.1-1.el7.elrepo.x86_64)
Примечание 2:
Перед началом настройки балансировщика haproxy обязательно настройте и стартаните ClickHouse на обеих нодах. Про настройку. Главное сетевые настройки укажите, чтобы можно было подключатся с другого компьютера, и пользователь чтобы существовал которому разрешено подключатся к ClickHouse серверу. И только после этого настраивайте и стартуйте балансировщик haproxy.
Теги для поиска:
#manual #loadbalance #balancing #инструкция #балансировка #балансировщик #tcp #haproxy #medov_alexey


Stanislav
24.08.2018
15:22:34
Или взять дебиан 9 и поставить пакет https://packages.debian.org/stretch/libnginx-mod-stream
Без дополнительного сервиса на балансировщике
И без пересборок чего-либо :)

Alexey
24.08.2018
15:25:05

Stanislav
24.08.2018
15:25:41
подключить, значит, надо

Alexey
24.08.2018
15:27:15

Google

Alexey
24.08.2018
15:27:20
Prerequisites
Latest open source NGINX built with the --with-stream configuration flag, or latest NGINX Plus (no extra build steps required)
Вот что сказазано для поддержки TCP требуется
короче я обошелся без nginx

Stanislav
24.08.2018
15:29:14
Заодно и http через haproxy можно
А вообще - load_module в помощь
В дебиане включение модуля - симлинк в modules-enabled на файл в modules-available

Yuri
24.08.2018
15:49:01

prll
24.08.2018
15:51:32
а какая odbc либа использовалась? если libiodbc то у нее могут быть немного другой формат конфига и расположение

Yuriy
24.08.2018
16:00:49
/stat@combot

Combot
24.08.2018
16:00:50
combot.org/c/-1001080295593

Yuri
24.08.2018
16:10:06

prll
24.08.2018
16:16:38
ах еще и макос? тогда там конфиг совсем далеко
вопрос с чем clickhouse-odbc.dylib собирали unixodbc или libiodbc

Александр
24.08.2018
16:41:20
Спасибо!

Рулон
24.08.2018
17:34:22
Щас облако запустят, и администрировать не придётся)))

Yuri
24.08.2018
18:40:54

Denis
24.08.2018
19:39:50
А кто-нибудь пользуется engine=Merge ?
Я тестирую этот движок и вроде все хорошо с ним.
Хочется переименовать старую таблицу X в X_old и начать писать в новую X_new с другим партриционированием и другой сортировкой и накрыть их X engine=Merge.
(переложить тяжело, в старой данных очень много, со временем просто они дропнутся).

Александр
24.08.2018
19:45:46

Denis
24.08.2018
19:47:38
ну у меня будет 2 таблицы. _old _new

Google

molo4ko
24.08.2018
20:06:41
как посчитать среднее время “сессии”, если в таблицу с событиями пишутся login/logout? что-то на замену lag

Bulat
24.08.2018
20:33:48
join таблицы с собой не работает?
select user_id, a.ts as start, min(b.ts) as end from my_table a join my_table b on a.user_id = b.user_id where a.ts < b.ts and a.type = 'login' and b.type = 'logout'
group by user_id, a.ts

molo4ko
24.08.2018
20:39:11
ну хотелось бы не джойнить) наверное, попробую какой-то комбинацией groupArray и дальше руками

Bulat
24.08.2018
20:40:51
ага, если гарантировать, что данные не терялись, то можно собрать в два массива логины и логауты)

Александр
24.08.2018
20:47:13

Renat
24.08.2018
20:50:26

Mike
24.08.2018
21:40:48
поищите, выше есть ссылка на SO, вокруг неё какое-то обсуждение было


Alexey
24.08.2018
22:36:11
@milovidov_an не планируется что-то типа такого функционала добавлять?
Ситуация: есть много файлов с данными, которые превышают max_insert_block_size и соответственно CH бьет это дело на разные блоки в соответствии с этой настройкой. И вот у меня данных на 3 блока, один блок вставился на в середине второго блока нашлась ошибка в данных и запрос упал. В CH осталась первый блок данных, но мне нужно: либо записалось все, либо ничего. Как такого можно достичь? Кто-то сталкивался с подобной потребностью?
Каждый раз держим возможность реализации этой функциональности "в уме", но ещё не запланировали и пока не собирались делать.
По-сути, это - вставка данных в одной транзакции. Уже сейчас ClickHouse работает так, что вставляемые данные пишутся во временные куски, которые затем атомарно добавляются в рабочий набор. Можно было бы сделать такое для многих кусков. Но есть следующие мелкие сложности:
1. Надо сделать минимальную поддержку транзакций, чтобы атомарно переименовать более одной директории. То есть, писать лог в файл, fsync его, восстанавливаться при старте. Это небольшая проблема.
2. За один INSERT может добавиться много временных кусков. Потом они все сразу попадут в рабочий набор. Например, в рабочий набор в один момент попадает 1000 кусков - и сразу же возникает большая нагрузка из-за мержей, а следующие INSERT-ы отваливаются из-за Too many parts. А в худшем случае очень большого INSERT-а будет плохо файловой системе. Вывод - надо мержить вставляемые куски ещё до того, как завершён INSERT.
3. Есть связанная задача - выполнять несколько SELECT-ов из одного консистентного снэпшота. Например, сделать два запроса - для таблицы и для графика в отчёте - и чтобы они показывали одинаковые данные, когда данные постоянно обновляются. В ClickHouse внутри уже есть нужная функциональность - по сути, SELECT берёт снэпшот из таблицы, а потом из него читает. Обычный синтаксис BEGIN/COMMIT почти подходит для всего, что перечислено, но всё-таки не совсем. Если есть несколько запросов из разных таблиц, то мы хотим создать снепшот для всех на один момент времени. И ещё есть мелочь - надо создавать снепшот не для всей таблицы, а для той части (тех партиций), которые будем читать.


molo4ko
24.08.2018
23:57:44
В какую сторону копать при таких записях в replication_queue?
shard_1 table_name node0 279 queue-0004917503 MERGE_PARTS 2018-08-22 01:52:38 0 REDACTED 20180801_20180820_678552_681247_1319 ['20180801_20180820_678552_681240_1318','20180819_20180820_681241_681247_2'] 0 0 105 Poco::Exception. Code: 1000, e.code() = 0, e.displayText() = Timeout: connect timed out: REDACTED:9009, e.what() = Timeout 2018-08-24 23:55:08 186659 Not merging into part 20180801_20180820_678552_681247_1319 because part 20180801_20180820_678552_681240_1318 is not ready yet (log entry for that part is being processed). 2018-08-24 23:55:38

Denis
25.08.2018
06:05:25

Sergey
25.08.2018
06:32:10


Александр
25.08.2018
08:21:56
Каждый раз держим возможность реализации этой функциональности "в уме", но ещё не запланировали и пока не собирались делать.
По-сути, это - вставка данных в одной транзакции. Уже сейчас ClickHouse работает так, что вставляемые данные пишутся во временные куски, которые затем атомарно добавляются в рабочий набор. Можно было бы сделать такое для многих кусков. Но есть следующие мелкие сложности:
1. Надо сделать минимальную поддержку транзакций, чтобы атомарно переименовать более одной директории. То есть, писать лог в файл, fsync его, восстанавливаться при старте. Это небольшая проблема.
2. За один INSERT может добавиться много временных кусков. Потом они все сразу попадут в рабочий набор. Например, в рабочий набор в один момент попадает 1000 кусков - и сразу же возникает большая нагрузка из-за мержей, а следующие INSERT-ы отваливаются из-за Too many parts. А в худшем случае очень большого INSERT-а будет плохо файловой системе. Вывод - надо мержить вставляемые куски ещё до того, как завершён INSERT.
3. Есть связанная задача - выполнять несколько SELECT-ов из одного консистентного снэпшота. Например, сделать два запроса - для таблицы и для графика в отчёте - и чтобы они показывали одинаковые данные, когда данные постоянно обновляются. В ClickHouse внутри уже есть нужная функциональность - по сути, SELECT берёт снэпшот из таблицы, а потом из него читает. Обычный синтаксис BEGIN/COMMIT почти подходит для всего, что перечислено, но всё-таки не совсем. Если есть несколько запросов из разных таблиц, то мы хотим создать снепшот для всех на один момент времени. И ещё есть мелочь - надо создавать снепшот не для всей таблицы, а для той части (тех партиций), которые будем читать.
Спасибо за развернутый ответ! Я полагаю, что не мы одни будем с нетерпением ждать этой фичи! Вы справитесь с этими сложностями, я уверен! :)
А может вам через Buffer таблицу вставлять по одному файлу? Buffer внутри успешные вставки объединит.
Мы уже использовали буфер движок, в какой-то момент начались пляски. Нам важно, что бы вся порция данных попадала в БД. Данные размазаны по 20 таблицам и если хотя бы в одну из них что-то не записалось, то эти «битые» данные не попадают в ротацию запросов на выборку. Битые же данные удаляются раз в час. После успешной вставки мы меняем version параметр конкретному пользователю и все данные в таблицы помечены этой версией. Таким образом мы стараемся поддерживать некое подобие транзакционности на уровне приложения. Без ролбэка, конечно же, но с гарантией, что версия обновится только тогда, когда все данные успешно записались в КХ.