ClickHouse перестает отвечать в процессе загрузки в него данных

2,154 views
Skip to first unread message

vvano353

unread,
Nov 14, 2016, 8:42:31 AM11/14/16
to ClickHouse
Добрый день.

Я столкнулся со следующей проблемой: я загружаю в базу текстовые данные, через jdbc драйвер, и в процессе в случайный момент времени сервер перестает отвечать (clickhouse-client также не может подключиться).
Загружаю файлы общим количеством ~100k файлов  объемом  ~30gb, 
СУБД развернута под виртуальной машиной VMware Ubuntu 16.04 64bit 3gb ОЗУ, 2 ядра
В качестве хоста используется компьютер Windows 7 64bit 8gb ОЗУ Intel-core i5-4460, 
В процессе загрузки сервер ведет себя специфически, выделяет себе память, затем освобождает ее (пиловидныый сигнал) и затем "умирает" совсем. 



Сопровождает каждое высвобождение памяти следующей ошибкой:
2016.11.13 22:40:23.307 [ 4 ] <Error> void DB::BackgroundProcessingPool::threadFunction(): Code: 240, e.displayText() = DB::Exception: Allocator: Cannot mremap., errno: 12, strerror: Cannot allocate memory: (while reading column Content): (while reading from part /opt/clickhouse//data/larav/materials/20161111_20161111_4814_6732_17/ from mark 0 to 1), e.what() = DB::Exception, Stack trace:

0. clickhouse-server(StackTrace::StackTrace()+0x16) [0x10b0806]
1. clickhouse-server(DB::Exception::Exception(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int)+0x1f) [0x1074bbf]
2. clickhouse-server(DB::throwFromErrno(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, int)+0x1a4) [0x10b9a74]
3. clickhouse-server(Allocator<false>::realloc(void*, unsigned long, unsigned long, unsigned long)+0x11d) [0x10c467d]
4. clickhouse-server() [0x12ec705]
5. clickhouse-server() [0x12ececb]
6. clickhouse-server(DB::MergeTreeReader::readData(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, DB::IDataType const&, DB::IColumn&, unsigned long, unsigned long, unsigned long, bool)+0x631) [0x11f89c1]
7. clickhouse-server(DB::MergeTreeReader::readRange(unsigned long, unsigned long, DB::Block&)+0x323) [0x11f9123]
8. clickhouse-server(DB::MergeTreeBlockInputStream::readImpl()+0x1098) [0x11fcff8]
9. clickhouse-server(DB::IProfilingBlockInputStream::read()+0x2ca) [0x12ba5ca]
10. clickhouse-server(DB::ExpressionBlockInputStream::readImpl()+0x2d) [0x12cfb0d]
11. clickhouse-server(DB::IProfilingBlockInputStream::read()+0x2ca) [0x12ba5ca]
12. clickhouse-server(DB::MaterializingBlockInputStream::readImpl()+0x30) [0x12379e0]
13. clickhouse-server(DB::IProfilingBlockInputStream::read()+0x2ca) [0x12ba5ca]
14. clickhouse-server(DB::MergingSortedBlockInputStream::init(DB::Block&, std::vector<DB::IColumn*, std::allocator<DB::IColumn*> >&)+0xd8) [0x12c3e38]
15. clickhouse-server(DB::MergingSortedBlockInputStream::readImpl()+0xc1) [0x12c5501]
16. clickhouse-server(DB::IProfilingBlockInputStream::read()+0x2ca) [0x12ba5ca]
17. clickhouse-server(DB::MergeTreeDataMerger::mergePartsToTemporaryPart(std::vector<std::shared_ptr<DB::MergeTreeDataPart const>, std::allocator<std::shared_ptr<DB::MergeTreeDataPart const> > >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, DB::MergeListEntry&, unsigned long, long, DB::DiskSpaceMonitor::Reservation*)+0x187f) [0x123673f]
18. clickhouse-server(DB::StorageMergeTree::merge(unsigned long, bool, DB::BackgroundProcessingPool::Context*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool)+0x589) [0x1185579]
19. clickhouse-server(DB::StorageMergeTree::mergeTask(DB::BackgroundProcessingPool::Context&)+0x19d) [0x1185b3d]
20. clickhouse-server(DB::BackgroundProcessingPool::threadFunction()+0x47a) [0x11d813a]
21. clickhouse-server(execute_native_thread_routine+0x20) [0x354e2a0]
22. /lib/x86_64-linux-gnu/libpthread.so.0(+0x770a) [0x7fe088dbd70a]
23. /lib/x86_64-linux-gnu/libc.so.6(clone+0x6d) [0x7fe0883de82d]



Таблица в которую заливаю данные:


CREATE TABLE example
.materials
(
   
PutDate Date,
   
PutDateTime DateTime,
 
Content String,
 
Url String
   
)
ENGINE
= MergeTree(PutDate, (Url, PutDate), 8192); |



Код которым заливаю данные:
if (line.hasOption("K")) {

Connection conn = DriverManager.getConnection("jdbc:clickhouse://192.168.25.128:8123/example");
SimpleDateFormat sdfd = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat sdfdt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String sql;
sql = "insert into  example.materials (PutDate,PutDateTime,Content,Url) FORMAT Values (?,?,?,?)";


Timestamp t;
String stri = null;
final File folder = new File("C:\\Users\\Admin\\files");
int y = 0;
for (final File fileEntry : folder.listFiles()) {

System.out.println(fileEntry.toPath()+" " + y);
y++;
//if(y<3000){continue;}
try{ stri = String.join("\n",Files.readAllLines(fileEntry.toPath(),Charset.forName("windows-1251")));}
catch (java.nio.charset.UnmappableCharacterException e){

stri = String.join("\n",Files.readAllLines(fileEntry.toPath(),Charset.forName("UTF-8")));


}
t = new Timestamp(new Date().getTime());
if(y%25==0){
conn.close();
conn = DriverManager.getConnection("jdbc:clickhouse://192.168.25.128:8123/example");
}
try{
java.sql.PreparedStatement stm = conn.prepareStatement(sql);
stm.setString(1,sdfd.format(new Date()));
stm.setString(2,sdfdt.format(new Date()));
stm.setString(3,stri);
stm.setString(4,fileEntry.toPath().toString());
stm.executeUpdate();

} catch (SQLException e) {

System.out.println(e.getMessage());

}
}
conn.close();

}



И получаю следующий лог:

C:\Users\Admin\files\107380.txt   5193
C:\Users\Admin\files\107382.txt   5194
C:\Users\Admin\files\107383.txt   5195
ноя 14, 2016 3:18:23 PM org.apache.http.impl.execchain.RetryExec execute
INFO: I/O exception (java.net.SocketException) caught when processing request to {}->http://192.168.25.128:8123: Connection reset by peer: socket write error
ноя 14, 2016 3:18:23 PM org.apache.http.impl.execchain.RetryExec execute
INFO: Retrying request to {}->http://192.168.25.128:8123
ClickHouse exception, code: 210, host: 192.168.25.128, port: 8123; Connect to 192.168.25.128:8123 [/192.168.25.128] failed: connect timed out
C:\Users\Admin\files\107384.txt   5196



Есть ли идеи с чем это может быть связано и как это решить?


Vadim Sichkarev

unread,
Nov 14, 2016, 3:22:48 PM11/14/16
to ClickHouse
Сложно понять что происходит в вашем примере и почему именно так вы это делаете.
1. Соединение с БД лучше произвести один раз до цикла. "Соединились" c КХ через JDBC и работаем как с обычной БД. Зачем вы каждый 25 раз закрываете коннект и заново инциализируете?!
2. Инициализация statement тоже самое: получили st, прошли циклом из файла 10000 записей, на каждый шаг выполнили addBatch, накопили 10000 батчей и отправили всё разом через executeBatch. См. пример на https://github.com/yandex/clickhouse-jdbc/blob/master/src/test/java/ru/yandex/clickhouse/integration/BatchInserts.java - я его для понимания использовал.
3. Если вам необходимо фиксировать время вставки записи, то лучше использовать в самой таблице таблице для поля определение DEFAULT today() или now(), чтобы исключить создание SimpleDateFormat в приложении.
4. Переменные используемые внутри цикла должны там же и формироваться, зачем они у вас объявлены за пределами цикла?
5. Files.readAllLines на мой взгляд лучше не использовать на больших массивах данных, читайте построчно - этим вы сэкономите память. Также метод чтения readAllLines у вас несколько раз присутствует. Тоже непонятно зачем.

По ошибкам части clickhouse-server думаю Алексей подскажет.

понедельник, 14 ноября 2016 г., 18:42:31 UTC+5 пользователь vvano353 написал:

man...@gmail.com

unread,
Nov 15, 2016, 9:18:08 PM11/15/16
to ClickHouse
Серверу не хватает оперативки.
3 GB мало.

vvano353

unread,
Nov 17, 2016, 3:32:40 AM11/17/16
to ClickHouse
А сколько надо? и какая тогда зависимости от кол-ва данных в базе? 

среда, 16 ноября 2016 г., 5:18:08 UTC+3 пользователь man...@gmail.com написал:

man...@gmail.com

unread,
Nov 17, 2016, 7:12:43 PM11/17/16
to ClickHouse
В данном случае необходимое количество оперативки определяется не общим объёмом данных, а средним размером строк в таблице.
Оперативка расходуется во время фоновых слияний. Посчитать, сколько нужно, можно так:

Максимальное количество фоновых слияний (настройка background_pool_size у профиля default, по-умолчанию 6)
умножить на максимальное количество кусков во время одного слияния (по-умолчанию 100 штук, но обычно меньше)
умножить на размер блока для слияния (8192 строки, не меняется)
умножить на средний размер строки в несжатом виде
умножить на два - максимальный оверхед на выделение памяти для буферов.

Допустим, размер строки в несжатом виде - 1 килобайт.
Тогда получается, что максимальное количество потребляемой оперативки на слияния, в худшем случае:

SELECT formatReadableSize(1024 * 2 * 8192 * 100 * 6)

9.38 GiB


Кстати, прямо сейчас у нас в разработке новый алгоритм слияния, в котором потребление оперативки уменьшено на порядки, за счёт обработки каждого столбца по отдельности. (К тому же скорость слияния увеличена примерно в 1.6 раз на наших данных.)
Reply all
Reply to author
Forward
0 new messages