2020-04-03 13:23:32 +00:00
---
toc_priority: 58
toc_title: Usage Recommendations
---
2020-03-20 10:10:48 +00:00
# Usage Recommendations {#usage-recommendations}
2017-12-28 15:13:23 +00:00
2020-03-20 10:10:48 +00:00
## CPU Scaling Governor {#cpu-scaling-governor}
2017-12-28 15:13:23 +00:00
2018-12-25 15:25:43 +00:00
Always use the `performance` scaling governor. The `on-demand` scaling governor works much worse with constantly high demand.
2017-12-28 15:13:23 +00:00
2020-03-20 10:10:48 +00:00
``` bash
2019-09-23 15:31:46 +00:00
$ echo 'performance' | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
2017-12-28 15:13:23 +00:00
```
2020-03-20 10:10:48 +00:00
## CPU Limitations {#cpu-limitations}
2017-12-28 15:13:23 +00:00
2020-03-20 10:10:48 +00:00
Processors can overheat. Use `dmesg` to see if the CPU’ s clock rate was limited due to overheating.
2017-12-28 15:13:23 +00:00
The restriction can also be set externally at the datacenter level. You can use `turbostat` to monitor it under a load.
2020-03-20 10:10:48 +00:00
## RAM {#ram}
2017-12-28 15:13:23 +00:00
2019-02-11 13:47:27 +00:00
For small amounts of data (up to ~200 GB compressed), it is best to use as much memory as the volume of data.
2017-12-28 15:13:23 +00:00
For large amounts of data and when processing interactive (online) queries, you should use a reasonable amount of RAM (128 GB or more) so the hot data subset will fit in the cache of pages.
2019-02-11 13:47:27 +00:00
Even for data volumes of ~50 TB per server, using 128 GB of RAM significantly improves query performance compared to 64 GB.
2017-12-28 15:13:23 +00:00
2018-11-22 19:52:26 +00:00
Do not disable overcommit. The value `cat /proc/sys/vm/overcommit_memory` should be 0 or 1. Run
2020-03-20 10:10:48 +00:00
``` bash
2019-09-23 15:31:46 +00:00
$ echo 0 | sudo tee /proc/sys/vm/overcommit_memory
2018-11-22 19:52:26 +00:00
```
2020-03-20 10:10:48 +00:00
## Huge Pages {#huge-pages}
2017-12-28 15:13:23 +00:00
Always disable transparent huge pages. It interferes with memory allocators, which leads to significant performance degradation.
2020-03-20 10:10:48 +00:00
``` bash
2019-09-23 15:31:46 +00:00
$ echo 'never' | sudo tee /sys/kernel/mm/transparent_hugepage/enabled
2017-12-28 15:13:23 +00:00
```
Use `perf top` to watch the time spent in the kernel for memory management.
Permanent huge pages also do not need to be allocated.
2020-03-20 10:10:48 +00:00
## Storage Subsystem {#storage-subsystem}
2017-12-28 15:13:23 +00:00
If your budget allows you to use SSD, use SSD.
If not, use HDD. SATA HDDs 7200 RPM will do.
Give preference to a lot of servers with local hard drives over a smaller number of servers with attached disk shelves.
But for storing archives with rare queries, shelves will work.
2020-03-20 10:10:48 +00:00
## RAID {#raid}
2017-12-28 15:13:23 +00:00
When using HDD, you can combine their RAID-10, RAID-5, RAID-6 or RAID-50.
2020-03-20 10:10:48 +00:00
For Linux, software RAID is better (with `mdadm` ). We don’ t recommend using LVM.
2017-12-28 15:13:23 +00:00
When creating RAID-10, select the `far` layout.
If your budget allows, choose RAID-10.
If you have more than 4 disks, use RAID-6 (preferred) or RAID-50, instead of RAID-5.
2020-03-20 10:10:48 +00:00
When using RAID-5, RAID-6 or RAID-50, always increase stripe\_cache\_size, since the default value is usually not the best choice.
2017-12-28 15:13:23 +00:00
2020-03-20 10:10:48 +00:00
``` bash
2019-09-23 15:31:46 +00:00
$ echo 4096 | sudo tee /sys/block/md2/md/stripe_cache_size
2017-12-28 15:13:23 +00:00
```
Calculate the exact number from the number of devices and the block size, using the formula: `2 * num_devices * chunk_size_in_bytes / 4096` .
2018-11-22 17:34:16 +00:00
A block size of 1024 KB is sufficient for all RAID configurations.
2017-12-28 15:13:23 +00:00
Never set the block size too small or too large.
You can use RAID-0 on SSD.
Regardless of RAID use, always use replication for data security.
2020-03-20 10:10:48 +00:00
Enable NCQ with a long queue. For HDD, choose the CFQ scheduler, and for SSD, choose noop. Don’ t reduce the ‘ readahead’ setting.
2017-12-28 15:13:23 +00:00
For HDD, enable the write cache.
2020-03-20 10:10:48 +00:00
## File System {#file-system}
2017-12-28 15:13:23 +00:00
Ext4 is the most reliable option. Set the mount options `noatime, nobarrier` .
2020-03-20 10:10:48 +00:00
XFS is also suitable, but it hasn’ t been as thoroughly tested with ClickHouse.
2017-12-28 15:13:23 +00:00
Most other file systems should also work fine. File systems with delayed allocation work better.
2020-03-20 10:10:48 +00:00
## Linux Kernel {#linux-kernel}
2017-12-28 15:13:23 +00:00
2020-03-20 10:10:48 +00:00
Don’ t use an outdated Linux kernel.
2017-12-28 15:13:23 +00:00
2020-03-20 10:10:48 +00:00
## Network {#network}
2017-12-28 15:13:23 +00:00
If you are using IPv6, increase the size of the route cache.
The Linux kernel prior to 3.2 had a multitude of problems with IPv6 implementation.
Use at least a 10 GB network, if possible. 1 Gb will also work, but it will be much worse for patching replicas with tens of terabytes of data, or for processing distributed queries with a large amount of intermediate data.
2020-03-20 10:10:48 +00:00
## ZooKeeper {#zookeeper}
2017-12-28 15:13:23 +00:00
2020-03-20 10:10:48 +00:00
You are probably already using ZooKeeper for other purposes. You can use the same installation of ZooKeeper, if it isn’ t already overloaded.
2017-12-28 15:13:23 +00:00
2020-03-20 10:10:48 +00:00
It’ s best to use a fresh version of ZooKeeper – 3.4.9 or later. The version in stable Linux distributions may be outdated.
2017-12-28 15:13:23 +00:00
2020-03-20 10:10:48 +00:00
You should never use manually written scripts to transfer data between different ZooKeeper clusters, because the result will be incorrect for sequential nodes. Never use the “zkcopy” utility for the same reason: https://github.com/ksprojects/zkcopy/issues/15
2018-09-04 11:18:59 +00:00
If you want to divide an existing ZooKeeper cluster into two, the correct way is to increase the number of its replicas and then reconfigure it as two independent clusters.
2018-08-28 17:07:01 +00:00
Do not run ZooKeeper on the same servers as ClickHouse. Because ZooKeeper is very sensitive for latency and ClickHouse may utilize all available system resources.
2017-12-28 15:13:23 +00:00
With the default settings, ZooKeeper is a time bomb:
2020-03-20 10:10:48 +00:00
> The ZooKeeper server won’ t delete files from old snapshots and logs when using the default configuration (see autopurge), and this is the responsibility of the operator.
2017-12-28 15:13:23 +00:00
This bomb must be defused.
The ZooKeeper (3.5.1) configuration below is used in the Yandex.Metrica production environment as of May 20, 2017:
zoo.cfg:
2020-03-20 10:10:48 +00:00
``` bash
2017-12-28 15:13:23 +00:00
# http://hadoop.apache.org/zookeeper/docs/current/zookeeperAdmin.html
# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
initLimit=30000
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=10
maxClientCnxns=2000
maxSessionTimeout=60000000
# the directory where the snapshot is stored.
2020-03-18 13:02:32 +00:00
dataDir=/opt/zookeeper/{{ '{{' }} cluster['name'] {{ '}}' }}/data
2017-12-28 15:13:23 +00:00
# Place the dataLogDir to a separate physical disc for better performance
2020-03-18 13:02:32 +00:00
dataLogDir=/opt/zookeeper/{{ '{{' }} cluster['name'] {{ '}}' }}/logs
2017-12-28 15:13:23 +00:00
autopurge.snapRetainCount=10
autopurge.purgeInterval=1
# To avoid seeks ZooKeeper allocates space in the transaction log file in
# blocks of preAllocSize kilobytes. The default block size is 64M. One reason
# for changing the size of the blocks is to reduce the block size if snapshots
# are taken more often. (Also, see snapCount).
preAllocSize=131072
# Clients can submit requests faster than ZooKeeper can process them,
# especially if there are a lot of clients. To prevent ZooKeeper from running
# out of memory due to queued requests, ZooKeeper will throttle clients so that
# there is no more than globalOutstandingLimit outstanding requests in the
# system. The default limit is 1,000.ZooKeeper logs transactions to a
# transaction log. After snapCount transactions are written to a log file a
# snapshot is started and a new transaction log file is started. The default
# snapCount is 10,000.
snapCount=3000000
# If this option is defined, requests will be will logged to a trace file named
# traceFile.year.month.day.
#traceFile=
# Leader accepts client connections. Default value is "yes". The leader machine
# coordinates updates. For higher update throughput at thes slight expense of
# read throughput the leader can be configured to not accept clients and focus
# on coordination.
leaderServes=yes
standaloneEnabled=false
2020-03-18 13:02:32 +00:00
dynamicConfigFile=/etc/zookeeper-{{ '{{' }} cluster['name'] {{ '}}' }}/conf/zoo.cfg.dynamic
2017-12-28 15:13:23 +00:00
```
Java version:
2020-03-20 10:10:48 +00:00
``` text
2018-04-23 06:20:21 +00:00
Java(TM) SE Runtime Environment (build 1.8.0_25-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)
2017-12-28 15:13:23 +00:00
```
JVM parameters:
2020-03-20 10:10:48 +00:00
``` bash
2020-03-18 13:02:32 +00:00
NAME=zookeeper-{{ '{{' }} cluster['name'] {{ '}}' }}
2017-12-28 15:13:23 +00:00
ZOOCFGDIR=/etc/$NAME/conf
# TODO this is really ugly
# How to find out, which jars are needed?
# seems, that log4j requires the log4j.properties file to be in the classpath
CLASSPATH="$ZOOCFGDIR:/usr/build/classes:/usr/build/lib/*.jar:/usr/share/zookeeper/zookeeper-3.5.1-metrika.jar:/usr/share/zookeeper/slf4j-log4j12-1.7.5.jar:/usr/share/zookeeper/slf4j-api-1.7.5.jar:/usr/share/zookeeper/servlet-api-2.5-20081211.jar:/usr/share/zookeeper/netty-3.7.0.Final.jar:/usr/share/zookeeper/log4j-1.2.16.jar:/usr/share/zookeeper/jline-2.11.jar:/usr/share/zookeeper/jetty-util-6.1.26.jar:/usr/share/zookeeper/jetty-6.1.26.jar:/usr/share/zookeeper/javacc.jar:/usr/share/zookeeper/jackson-mapper-asl-1.9.11.jar:/usr/share/zookeeper/jackson-core-asl-1.9.11.jar:/usr/share/zookeeper/commons-cli-1.2.jar:/usr/src/java/lib/*.jar:/usr/etc/zookeeper"
ZOOCFG="$ZOOCFGDIR/zoo.cfg"
ZOO_LOG_DIR=/var/log/$NAME
USER=zookeeper
GROUP=zookeeper
PIDDIR=/var/run/$NAME
PIDFILE=$PIDDIR/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
JAVA=/usr/bin/java
ZOOMAIN="org.apache.zookeeper.server.quorum.QuorumPeerMain"
ZOO_LOG4J_PROP="INFO,ROLLINGFILE"
JMXLOCALONLY=false
2020-03-18 13:02:32 +00:00
JAVA_OPTS="-Xms{{ '{{' }} cluster.get('xms','128M') {{ '}}' }} \
-Xmx{{ '{{' }} cluster.get('xmx','1G') {{ '}}' }} \
2017-12-28 15:13:23 +00:00
-Xloggc:/var/log/$NAME/zookeeper-gc.log \
-XX:+UseGCLogFileRotation \
-XX:NumberOfGCLogFiles=16 \
-XX:GCLogFileSize=16M \
-verbose:gc \
-XX:+PrintGCTimeStamps \
-XX:+PrintGCDateStamps \
-XX:+PrintGCDetails
-XX:+PrintTenuringDistribution \
-XX:+PrintGCApplicationStoppedTime \
-XX:+PrintGCApplicationConcurrentTime \
-XX:+PrintSafepointStatistics \
-XX:+UseParNewGC \
-XX:+UseConcMarkSweepGC \
-XX:+CMSParallelRemarkEnabled"
```
Salt init:
2020-03-20 10:10:48 +00:00
``` text
2020-03-18 13:02:32 +00:00
description "zookeeper-{{ '{{' }} cluster['name'] {{ '}}' }} centralized coordination service"
2017-12-28 15:13:23 +00:00
start on runlevel [2345]
stop on runlevel [!2345]
respawn
limit nofile 8192 8192
pre-start script
2020-03-18 13:02:32 +00:00
[ -r "/etc/zookeeper-{{ '{{' }} cluster['name'] {{ '}}' }}/conf/environment" ] || exit 0
. /etc/zookeeper-{{ '{{' }} cluster['name'] {{ '}}' }}/conf/environment
2017-12-28 15:13:23 +00:00
[ -d $ZOO_LOG_DIR ] || mkdir -p $ZOO_LOG_DIR
chown $USER:$GROUP $ZOO_LOG_DIR
end script
script
2020-03-18 13:02:32 +00:00
. /etc/zookeeper-{{ '{{' }} cluster['name'] {{ '}}' }}/conf/environment
2017-12-28 15:13:23 +00:00
[ -r /etc/default/zookeeper ] & & . /etc/default/zookeeper
if [ -z "$JMXDISABLE" ]; then
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.local.only=$JMXLOCALONLY"
fi
2020-03-18 13:02:32 +00:00
exec start-stop-daemon --start -c $USER --exec $JAVA --name zookeeper-{{ '{{' }} cluster['name'] {{ '}}' }} \
2017-12-28 15:13:23 +00:00
-- -cp $CLASSPATH $JAVA_OPTS -Dzookeeper.log.dir=${ZOO_LOG_DIR} \
-Dzookeeper.root.logger=${ZOO_LOG4J_PROP} $ZOOMAIN $ZOOCFG
end script
```
2020-03-30 13:20:50 +00:00
{## [Original article ](https://clickhouse.tech/docs/en/operations/tips/ ) ##}