CLICKHOUSE-2724: website refactoring (#668)

* Split website and doc

* Add Host directive to robots.txt

* Make new favicon.ico from svg

* Reformat code

* Add some obscurity to email to limit it's inclusion to email spam databases

* Mention SQL in descriptions

* Put logo near main title

* Add navbar

* Update feedback text on tutorial page

* Reformat code on tutorial page

* Better inline svg

* Move javascript to bottom in reference

* Mark external links on main & tutorial

* Copy footer from main to tutorial

* Move Telegram higher

* Get rid of hidden content

* Update jQuery + add it on index

* Rewrite plain JS with jQuery on index

* Swap Contacts and Download

* Some title tuning

* Move Source link to corner

* Slow scroll

* New first screen

* First screen tuning

* Add github pages script

* Checkout in proper place

* more nofollow

* Basic mobile support

* Add some temporary icon (SIL licensed)

* Fix horizontal scroll on mobile

* Re-order paragraphs

* Sync paragraphs with their index

* Add one more grey block

* Fix scroll to top

* better offset

* Reformat code

* Add social paragraph

* Better word

* Font tuning

* More font/offset tuning

* Increase navbar padding

* Basic minify & livereload via gulp

* Add styles to default in gulp

* Do not minify html in reference

* Add og:image header

* "build" gulp target

* Add readme for website

* Max-width for navbar

* Use different placeholder

* Tune some margins

* Do not center buttons

* Tune navbar padding

* s/an/a/

* Larger font at logo

* Increase padding at hero

* Yet another placeholder + tune padding on buttons

* Basic support for website inside Docker

* Listen for IPv6 inside Docker

* s/available/enabled/g

* nginx tuning

* add gzip_min_length

* not so dark "fork me" badge

* do not commit build results

* move "fork me" to right side

* Tune styles and texts

* tune mobile version

* text fix

* text fix

* text fix

* publish presentations

* fix navbar styling

* fix id name

* Support actual deployment to either prod and test

* tune logo margin

* Mention ClickHouse Docker images

* style tuning

* disable mix-blend-mode on mobile

* copy robots.txt
This commit is contained in:
Ivan Blinkov 2017-04-10 17:24:53 +03:00 committed by alexey-milovidov
parent ba9590d340
commit 6a51c66424
24 changed files with 12147 additions and 3 deletions

4
.gitignore vendored
View File

@ -223,3 +223,7 @@ config-preprocessed.xml
# Ignore symlink to private repository
/private
# Gulp dependencies used to minify website
node_modules
public

Binary file not shown.

Before

Width:  |  Height:  |  Size: 318 B

View File

@ -1,2 +0,0 @@
User-agent: *
Allow: /

4
website/Dockerfile Normal file
View File

@ -0,0 +1,4 @@
FROM nginx:mainline
COPY public /usr/share/nginx/html
COPY nginx/nginx.conf /etc/nginx/nginx.conf
COPY nginx/default.conf /etc/nginx/conf.d/default.conf

4
website/README.md Executable file
View File

@ -0,0 +1,4 @@
ClickHouse website quickstart:
1. If npm is not installed: `apt-get install npm` for Debian/Ubuntu, `brew install npm` for Mac OS or download and install manually https://nodejs.org/en/download/
2. Run setup\_gulp.sh once to install prerequisites via npm
3. Use `gulp build` to minify website to "public" folder or just `gulp` to run local webserver with livereload serving it

View File

@ -2116,7 +2116,7 @@ try { var yaCounter18343495 = new Ya.Metrika({id:18343495,
<noscript><div><img src="https://mc.yandex.ru/watch/18343495" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<!-- /Yandex.Metrika counter -->
<script type="text/javascript" src="https://yandex.st/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript" src="https://yastatic.net/jquery/3.1.1/jquery.min.js"></script>
<div class='island'>

BIN
website/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 B

95
website/gulpfile.js Normal file
View File

@ -0,0 +1,95 @@
var gulp = require('gulp');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var cleanCss = require('gulp-clean-css');
var imagemin = require('gulp-imagemin');
var sourcemaps = require('gulp-sourcemaps');
var htmlmin = require('gulp-htmlmin');
var minifyInline = require('gulp-minify-inline');
var del = require('del');
var connect = require('gulp-connect');
var outputDir = 'public';
var paths = {
htmls: ['*.html', '!reference_ru.html', '!reference_en.html'],
reference: ['reference_ru.html', 'reference_en.html'],
scripts: ['*.js', '!gulpfile.js'],
styles: ['*.css'],
images: ['*.png', '*.ico'],
robotstxt: ['robots.txt'],
presentations: ['../doc/presentations/**']
};
gulp.task('clean', function () {
return del([outputDir + '**']);
});
gulp.task('reference', [], function () {
return gulp.src(paths.reference)
.pipe(minifyInline())
.pipe(gulp.dest(outputDir))
.pipe(connect.reload())
});
gulp.task('presentations', [], function () {
return gulp.src(paths.presentations)
.pipe(gulp.dest(outputDir + '/presentations'))
.pipe(connect.reload())
});
gulp.task('robotstxt', [], function () {
return gulp.src(paths.robotstxt)
.pipe(gulp.dest(outputDir))
.pipe(connect.reload())
});
gulp.task('htmls', ['reference', 'robotstxt', 'presentations'], function () {
return gulp.src(paths.htmls)
.pipe(htmlmin({collapseWhitespace: true}))
.pipe(minifyInline())
.pipe(gulp.dest(outputDir))
.pipe(connect.reload())
});
gulp.task('scripts', [], function () {
return gulp.src(paths.scripts)
.pipe(sourcemaps.init())
.pipe(uglify())
.pipe(sourcemaps.write())
.pipe(gulp.dest(outputDir))
.pipe(connect.reload())
});
gulp.task('styles', [], function () {
return gulp.src(paths.styles)
.pipe(cleanCss())
.pipe(gulp.dest(outputDir))
.pipe(connect.reload())
});
gulp.task('images', [], function () {
return gulp.src(paths.images)
.pipe(imagemin({optimizationLevel: 9}))
.pipe(gulp.dest(outputDir))
.pipe(connect.reload())
});
gulp.task('watch', function () {
gulp.watch(paths.htmls, ['htmls']);
gulp.watch(paths.scripts, ['scripts']);
gulp.watch(paths.images, ['images']);
});
gulp.task('connect', function() {
connect.server({
root: outputDir,
port: 8080,
keepalive: true,
livereload: true
})
});
gulp.task('build', ['htmls', 'scripts', 'styles', 'images']);
gulp.task('default', ['build', 'watch', 'connect']);

884
website/index.html Normal file
View File

@ -0,0 +1,884 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<title>ClickHouse — open source distributed column-oriented DBMS</title>
<link rel="shortcut icon" href="favicon.ico"/>
<meta property="og:title" content="ClickHouse DBMS"/>
<meta property="og:description"
content="ClickHouse is an open source column-oriented database management system that allows generating analytical data reports in real time using SQL queries."/>
<meta property="og:type" content="website"/>
<meta property="og:url" content="https://clickhouse.yandex"/>
<meta property="og:image" content="https://clickhouse.yandex/logo.png"/>
<meta property="twitter:title" content="ClickHouse DBMS"/>
<meta name="description"
content="ClickHouse is an open source distributed column-oriented database management system that allows generating analytical data reports in real time using SQL queries. Сreated by Yandex ClickHouse manages extremely large volumes of data in a stable and sustainable manner."/>
<meta name="keywords"
content="ClickHouse, DBMS, OLAP, relational, analytics, analytical, big data, open-source, SQL, web-analytics" />
<style type="text/css">
@font-face {
font-family: 'Yandex Sans Text Web';
src: url(https://yastatic.net/adv-www/_/yy5JveR58JFkc97waf-xp0i6_jM.eot);
src: url(https://yastatic.net/adv-www/_/yy5JveR58JFkc97waf-xp0i6_jM.eot?#iefix) format('embedded-opentype'),
url(https://yastatic.net/adv-www/_/CYblzLEXzCqQIvrYs7QKQe2omRk.woff2) format('woff2'),
url(https://yastatic.net/adv-www/_/pUcnOdRwl83MvPPzrNomhyletnA.woff) format('woff'),
url(https://yastatic.net/adv-www/_/vNFEmXOcGYKJ4AAidUprHWoXrLU.ttf) format('truetype'),
url(https://yastatic.net/adv-www/_/0w7OcWZM_QLP8x-LQUXFOgXO6dE.svg#YandexSansTextWeb-Bold) format('svg');
font-weight: 700;
font-style: normal;
font-stretch: normal
}
@font-face {
font-family: 'Yandex Sans Text Web';
src: url(https://yastatic.net/adv-www/_/LI6l3L2RqcgxBe2pXmuUha37czQ.eot);
src: url(https://yastatic.net/adv-www/_/LI6l3L2RqcgxBe2pXmuUha37czQ.eot?#iefix) format('embedded-opentype'),
url(https://yastatic.net/adv-www/_/z3MYElcut0R2MF_Iw1RDNrstgYs.woff2) format('woff2'),
url(https://yastatic.net/adv-www/_/1jvKJ_-hCXl3s7gmFl-y_-UHTaI.woff) format('woff'),
url(https://yastatic.net/adv-www/_/9nzjfpCR2QHvK1EzHpDEIoVFGuY.ttf) format('truetype'),
url(https://yastatic.net/adv-www/_/gwyBTpxSwkFCF1looxqs6JokKls.svg#YandexSansTextWeb-Regular) format('svg');
font-weight: 400;
font-style: normal;
font-stretch: normal
}
@font-face {
font-family: 'Yandex Sans Text Web';
src: url(https://yastatic.net/adv-www/_/ayAFYoY8swgBLhq_I56tKj2JftU.eot);
src: url(https://yastatic.net/adv-www/_/ayAFYoY8swgBLhq_I56tKj2JftU.eot?#iefix) format('embedded-opentype'),
url(https://yastatic.net/adv-www/_/lGQcYklLVV0hyvz1HFmFsUTj8_0.woff2) format('woff2'),
url(https://yastatic.net/adv-www/_/f0AAJ9GJ4iiwEmhG-7PWMHk6vUY.woff) format('woff'),
url(https://yastatic.net/adv-www/_/4UDe4nlVvgEJ-VmLWNVq3SxCsA.ttf) format('truetype'),
url(https://yastatic.net/adv-www/_/EKLr1STNokPqxLAQa_RyN82pL98.svg#YandexSansTextWeb-Light) format('svg');
font-weight: 300;
font-style: normal;
font-stretch: normal
}
@font-face {
font-family: 'Yandex Sans Display Web';
src: url(https://yastatic.net/adv-www/_/H63jN0veW07XQUIA2317lr9UIm8.eot);
src: url(https://yastatic.net/adv-www/_/H63jN0veW07XQUIA2317lr9UIm8.eot?#iefix) format('embedded-opentype'),
url(https://yastatic.net/adv-www/_/sUYVCPUAQE7ExrvMS7FoISoO83s.woff2) format('woff2'),
url(https://yastatic.net/adv-www/_/v2Sve_obH3rKm6rKrtSQpf-eB7U.woff) format('woff'),
url(https://yastatic.net/adv-www/_/PzD8hWLMunow5i3RfJ6WQJAL7aI.ttf) format('truetype'),
url(https://yastatic.net/adv-www/_/lF_KG5g4tpQNlYIgA0e77fBSZ5s.svg#YandexSansDisplayWeb-Regular) format('svg');
font-weight: 400;
font-style: normal;
font-stretch: normal
}
@font-face {
font-family: 'Yandex Sans Display Web';
src: url(https://yastatic.net/adv-www/_/g8_MyyKVquSZ3xEL6tarK__V9Vw.eot);
src: url(https://yastatic.net/adv-www/_/g8_MyyKVquSZ3xEL6tarK__V9Vw.eot?#iefix) format('embedded-opentype'),
url(https://yastatic.net/adv-www/_/LGiRvlfqQHlWR9YKLhsw5e7KGNA.woff2) format('woff2'),
url(https://yastatic.net/adv-www/_/40vXwNl4eYYMgteIVgLP49dwmfc.woff) format('woff'),
url(https://yastatic.net/adv-www/_/X6zG5x_wO8-AtwJ-vDLJcKC5228.ttf) format('truetype'),
url(https://yastatic.net/adv-www/_/ZKhaR0m08c8CRRL77GtFKoHcLYA.svg#YandexSansDisplayWeb-Light) format('svg');
font-weight: 300;
font-style: normal;
font-stretch: normal
}
body {
background: #fff;
font: 300 14pt/200% 'Yandex Sans Text Web', Arial, sans-serif;
margin: 0;
padding: 0;
}
#navbar {
top: 0;
z-index: 100;
position: fixed;
width: 100%;
background: #fff;
border-bottom: 1px solid #efefef;
padding: 6px 0 0 0;
margin: 0;
}
#navbar-inner {
max-width: 1280px;
margin: 4px auto;
}
#logo {
color: #000;
text-decoration: none;
font-size: 110%;
}
#main-title {
font: 400 42pt/90% 'Yandex Sans Display Web', Arial, sans-serif;
margin: 0;
}
#title-logo {
margin: 1px 8px 0 13px;
}
#github {
bottom: 0;
right: 0;
z-index: 100;
position: fixed;
font-size: 85%;
font-weight: 400;
padding: 0 4em;
margin: 0 -4em 2.5em 0;
-webkit-transform: rotate(-45deg);
-moz-transform: rotate(-45deg);
-ms-transform: rotate(-45deg);
-o-transform: rotate(-45deg);
background: #fc0;
border: 2px solid #000;
mix-blend-mode: hard-light;
}
#github_link {
color: #000;
}
#github_link:hover {
color: #000;
}
.page {
max-width: 800px;
margin: auto;
}
h2 {
margin: 47px 0 23px;
font: 400 200%/133% 'Yandex Sans Display Web', Arial, sans-serif;
}
.smaller-font {
font-size: 80%;
}
a:link, a:visited {
color: #08f;
text-decoration: none;
}
a:hover, a:active {
color: #f00;
text-decoration: underline;
}
#top-menu {
margin: 12px 0 0 0;
font: 400 18pt 'Yandex Sans Display Web', Arial, sans-serif;
float: right;
}
.menu_item:link,
.menu_item:active,
.menu_item:visited {
margin: 0 8px 0 0;
padding: 5px;
color: #000;
}
.menu_item:hover, .index_item:hover {
padding-bottom: 4px;
border-bottom: 2px solid #fc0;
text-decoration: none;
}
.index_item:link,
.index_item:active,
.index_item:visited {
color: #ededed;
font: 300 100% 'Yandex Sans Display Web', Arial, sans-serif;
}
#short-description {
font: 300 125%/150% 'Yandex Sans Display Web', Arial, sans-serif;
margin: 0 1em 1.75em 0;
text-align: left;
}
#hero {
background: #555;
padding: 110px 0 40px 0;
color: #ededed;
}
#index_ul {
margin-top: 2px;
padding-left: 20px;
}
#slogan {
}
#placeholder {
width: 66%;
margin: 5% auto 0 auto;
}
.colored-block {
width: 100%;
padding: 20px 0 60px 0;
margin: 60px 0;
}
.colored-block>h2 {
margin-top: 0;
}
#performance {
background: #fc0;
}
#call_to_action, #benchmark_learn_more {
text-decoration: none;
padding-left: 18px;
font-size: 120%;
width: 182px;
height: 50px;
line-height: 50px;
display: block;
margin-bottom: 15px;
}
#call_to_action {
background: url('yandex-white-button.png') no-repeat;
color: #ededed;
}
#call_to_action:hover {
color: #fc0;
}
#benchmark_learn_more {
background: url('yandex-black-button.png') no-repeat;
float: right;
color: #000;
}
#grey-block {
background: #555;
color: #ededed;
}
#ubuntu-install {
overflow: auto;
overflow-y: hidden;
-ms-overflow-y: hidden;
}
#footer {
text-align: right;
padding: 8px 0 0 0;
color: #888;
font-size: 10pt;
}
code {
font: 13px/18px monospace, "Courier New";
display: block;
border-left: 5px solid #ffdb4d;
padding: 5px 10px;
background: #000;
color: #ccc;
}
ul {
margin: 0;
padding-left: 0;
}
ul.dashed {
list-style-type: none;
}
ul.dashed > li {
text-indent: 15px;
margin-top: -5px;
}
ul.dashed > li:before {
content: '— ';
text-indent: 1em;
}
.warranty {
margin-top: 6em;
font-size: 50%;
color: #888;
line-height: 150%;
border-top: 1px solid #888;
padding: 1em 0;
}
.distributive_selected {
color: #000;
font-weight: bold;
}
.distributive_not_selected {
color: #08f;
cursor: pointer;
border-bottom: 1px solid #08f;
}
.block-50 {
float: left;
display: block;
width: 50%;
}
.block-30 {
float: left;
display: block;
width: 30%;
}
.block-70 {
float: left;
display: block;
width: 70%;
}
.clear {
clear: both;
}
.orange {
fill: #fc0;
color: #fc0;
}
.red {
fill: #f00;
}
@media (max-width: 1023px) {
body {
font-size: 18pt;
}
#index_ul {
padding-left: 0;
margin: 0 0 30px -16px;
font-size: 90%;
}
#hero {
padding: 40px 0 10px 0;
}
.desktop-only {
display: none;
}
.page {
width: 90%;
margin: 0 auto;
}
.smaller-font {
font-size: 100%;
}
#navbar {
position: relative;
text-align: center;
margin: 1.33em 0;
padding: 0;
border: none;
}
#hero ul.dashed > li:before {
content: '';
}
#hero .index_item {
font-size: 110%;
}
#hero .dashed {
margin-bottom: 50px;
}
#call_to_action {
margin: 20px 0 40px 0;
}
#short-description {
margin-bottom: 40px;
}
#github {
position: relative;
padding: 0;
margin: 0;
text-align: center;
font-weight: 300;
font-size: 110%;
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-ms-transform: rotate(0deg);
-o-transform: rotate(0deg);
background: #fc0;
border: 0;
mix-blend-mode: normal;
}
#benchmark_learn_more, #call_to_action {
font-size: 90%;
}
.block-30, .block-50, .block-70 {
width: 100%;
float: none;
}
}
</style>
</head>
<body>
<div id="navbar">
<div id="navbar-inner">
<div id="top-menu" class="desktop-only">
<a class="menu_item" href="#quick-start">Quick Start</a>
<a class="menu_item" href="#performance">Performance</a>
<a class="menu_item" href="reference_en.html">Documentation</a>
<a class="menu_item" href="#contacts">Contacts</a>
</div>
<a id="logo" href="#">
<h1 id="main-title">
<svg id="title-logo" xmlns="http://www.w3.org/2000/svg" width="48" height="44" viewBox="0 0 9 8">
<path class="red" d="M0,7 h1 v1 h-1 z"></path>
<path class="orange" d="M0,0 h1 v7 h-1 z"></path>
<path class="orange" d="M2,0 h1 v8 h-1 z"></path>
<path class="orange" d="M4,0 h1 v8 h-1 z"></path>
<path class="orange" d="M6,0 h1 v8 h-1 z"></path>
<path class="orange" d="M8,3.25 h1 v1.5 h-1 z"></path>
</svg>
ClickHouse
</h1>
</a>
</div>
</div>
<div id="hero">
<div class="page">
<div class="block-70">
<p id="short-description">ClickHouse is an <span class="orange">open&nbsp;source</span> column-oriented
database management system
capable of <span class="orange">real&nbsp;time</span> generation of analytical data reports using <span
class="orange">SQL</span>&nbsp;queries.</p>
<a id="call_to_action" href="#quick-start">
Quick Start
</a>
</div>
<div class="block-30">
<ul id="index_ul" class="dashed">
<li>
<a class="index_item" href="#blazing-fast">Blazing Fast</a>
</li>
<li>
<a class="index_item" href="#linearly-scalable">Linearly Scalable</a>
</li>
<li>
<a class="index_item" href="#hardware-efficient">Hardware Efficient</a>
</li>
<li>
<a class="index_item" href="#fault-tolerant">Fault Tolerant</a>
</li>
<li>
<a class="index_item" href="#feature-rich">Feature Rich</a>
</li>
<li>
<a class="index_item" href="#simple-and-handy">Simple and Handy</a>
</li>
<li>
<a class="index_item" href="#highly-reliable">Highly Reliable</a>
</li>
</ul>
</div>
<div class="clear"></div>
</div>
</div>
<a id="github_link"
href="https://github.com/yandex/ClickHouse"
rel="external nofollow"
target="_blank"
><div id="github">Fork me on GitHub</div></a>
<div class="page">
<h2 id="slogan">ClickHouse. Just makes you think faster.</h2>
<div class="block-70">
<ul class="dashed">
<li>Run more queries in the same amount of time</li>
<li>Test more hypotheses</li>
<li>Slice and dice your data in many more new ways</li>
<li>Look at your data from new angles</li>
<li>Discover new dimensions</li>
</ul>
</div>
<div class="block-30">
<svg id="placeholder" class="desktop-only" viewBox="0 0 76 76" xmlns="http://www.w3.org/2000/svg">
<defs>
<rect id="path-1" x="0" y="16" width="60" height="60" rx="1"></rect>
<mask id="mask-2" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="60" height="60" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<rect id="path-3" x="16" y="0" width="60" height="60" rx="1"></rect>
<mask id="mask-4" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="60" height="60" fill="white">
<use xlink:href="#path-3"></use>
</mask>
<rect id="path-5" x="0" y="8" width="20" height="20" rx="1"></rect>
<mask id="mask-6" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="20" height="20" fill="white">
<use xlink:href="#path-5"></use>
</mask>
<rect id="path-7" x="8" y="0" width="20" height="20" rx="1"></rect>
<mask id="mask-8" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="20" height="20" fill="white">
<use xlink:href="#path-7"></use>
</mask>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round">
<g id="Clickhouse_2" transform="translate(-558.000000, -1293.000000)">
<g id="Group-11" transform="translate(558.000000, 1293.000000)">
<use id="Rectangle-33" stroke="#FFCC00" mask="url(#mask-2)" stroke-width="4" xlink:href="#path-1"></use>
<use id="Rectangle-33" stroke="#FFCC00" mask="url(#mask-4)" stroke-width="4" xlink:href="#path-3"></use>
<path d="M0.989013672,17.017334 L16.8210449,1.16748047" id="Path-26" stroke="#FFCC00" stroke-width="2"></path>
<path d="M59.0788574,74.9973145 L74.7983398,59.2650146" id="Path-26" stroke="#FFCC00" stroke-width="2"></path>
<path d="M59.1091309,17.1687012 L74.9368896,1.10351562" id="Path-26-Copy" stroke="#FFCC00" stroke-width="2"></path>
<path d="M1.07910156,17.2504883 L26.0395508,33.4033203" id="Path-26" stroke="#FFCC00" stroke-width="2"></path>
<path d="M17.2602539,1.18457031 L34.0175781,25.1796875" id="Path-26" stroke="#FFCC00" stroke-width="2"></path>
<path d="M51.2958984,25.4736328 L58.8277588,17" id="Path-26-Copy" stroke="#FFCC00" stroke-width="2"></path>
<path d="M1.01904297,50.942627 L25.9216309,75.064209" id="Path-26" stroke="#FFCC00" stroke-width="2" transform="translate(13.470337, 63.003418) scale(-1, 1) translate(-13.470337, -63.003418) "></path>
<path d="M44.1804199,51.300293 L58.9638672,75.010498" id="Path-26" stroke="#FFCC00" stroke-width="2"></path>
<path d="M52.0131836,43.1345215 L75.0227051,58.9299316" id="Path-26" stroke="#FFCC00" stroke-width="2"></path>
<g id="Group-3" transform="translate(25.000000, 24.000000)" stroke="#444444">
<use id="Rectangle-33" mask="url(#mask-6)" stroke-width="4" xlink:href="#path-5"></use>
<use id="Rectangle-33" mask="url(#mask-8)" stroke-width="4" xlink:href="#path-7"></use>
<path d="M19.2587891,1.08825684 L26.7729492,8.8046875" id="Path-26" stroke-width="2" transform="translate(23.015869, 4.946472) scale(-1, 1) translate(-23.015869, -4.946472) "></path>
<path d="M1.05773926,1.04125977 L8.82080078,8.9654541" id="Path-26" stroke-width="2" transform="translate(4.939270, 5.003357) scale(-1, 1) translate(-4.939270, -5.003357) "></path>
<path d="M1.12487793,18.887207 L9.26220703,26.8897705" id="Path-26" stroke-width="2" transform="translate(5.193542, 22.888489) scale(-1, 1) translate(-5.193542, -22.888489) "></path>
<path d="M19.038208,19.1968994 L26.9085693,26.9760742" id="Path-26" stroke-width="2" transform="translate(22.973389, 23.086487) scale(-1, 1) translate(-22.973389, -23.086487) "></path>
</g>
</g>
</g>
</g>
</svg>
</div>
<div class="clear"></div>
<h2 id="blazing-fast">Blazing Fast</h2>
<p>ClickHouse's performance <a href="benchmark.html">exceeds</a> comparable column-oriented DBMS currently available
on the market. It&nbsp;processes hundreds of millions to more than a billion rows and tens of gigabytes of data
per single server per second.</p>
<p>ClickHouse uses all available hardware to its full potential to process each query as fast as possible. The peak
processing performance for a single query (after decompression, only used columns) stands at more than 2&nbsp;terabytes
per second.</p>
</div>
<div id="performance" class="colored-block">
<div class="page">
<h2>ClickHouse works 100-1,000x faster than traditional approaches</h2>
<p>In contrast to data management methods, where vast amounts of raw data in its native format are available as
a "data lake" for any
given query, ClickHouse, in most cases, offers instant results: the data is processed faster than it&nbsp;takes
to make a query. Follow the link to see detailed benchmarks in comparison with other database management
systems.</p>
<a id="benchmark_learn_more" href="benchmark.html">
Learn more
</a>
<div class="clear"></div>
</div>
</div>
<div class="page">
<h2 id="linearly-scalable">Linearly Scalable</h2>
<p>ClickHouse allows companies to add servers to their clusters when necessary without investing time or money into
additional DBMS modification. The system has been successfully serving <a href="https://metrica.yandex.com/">Yandex.Metrica</a>,
while the servers just in its main cluster, located in six geographically distributed datacenters, have grown
from 60 to 394 in two years.</p>
<p>ClickHouse scales well both vertically and horizontally. ClickHouse is easily adaptable to perform both on
hundreds of node clusters, and on a single server or even virtual machine. It&nbsp;currently has installations
with more than two trillion rows per single node, as well as installations with 100 TB of storage per single
node.</p>
<h2 id="hardware-efficient">Hardware Efficient</h2>
<p>ClickHouse processes typical analytical queries two to three orders of magnitude faster than traditional
row-oriented systems with the same available IO throughput. The systems columnar format allows fitting more hot
data in the servers RAM, which leads to a shorter response time.</p>
<p>ClickHouse allows to minimize number of seeks for range queries, which increases efficiency of using rotational
drives, as it&nbsp;maintains locality of reference for stored data continually.</p>
<p>ClickHouse is CPU efficient because of its vectorized query execution and runtime code generation.</p>
<p>By minimizing data transfers for most types of queries, ClickHouse enables companies to manage their data and
create reports without using a network that supports high-performance computing.</p>
</div>
<div id="grey-block" class="colored-block">
<div class="page">
<h2 id="fault-tolerant">Fault Tolerant</h2>
<p>ClickHouse supports multi-master asynchronous replication and can be deployed across multiple datacenters.
Downtime of a single node or the whole datacenter wont affect the systems availability for reads and
writes.
Distributed reads are automatically balanced to live replicas without increasing latency. Replicated data
are
synchronized automatically or semi-automatically after the downtime.</p>
</div>
</div>
<div class="page">
<h2 id="feature-rich">Feature Rich</h2>
<p>ClickHouse features a number of built-in user-friendly web analytics capabilities, including probabilistic data
structures for fast and memory-efficient calculation of cardinalities and quantiles, or functions for addressing
URLs and IPs (both IPv4 and IPv6) as well as identifying dates, times and time zones.</p>
<p>Data management methods available in ClickHouse, such as arrays, array joins and nested data structures, are
extremely efficient for managing denormalized data.</p>
<p>Using ClickHouse allows joining both distributed data and co-located data, as the system supports local joins and
distributed joins. It&nbsp;also offers an opportunity to use external dictionaries, dimension tables loaded from
an external source, for seamless joins.</p>
<p>ClickHouse supports approximate query processing you can get results as fast as you want, which is
indispensable when dealing with terabytes and petabytes of data.</p>
<p>The systems conditional aggregate functions, calculation of totals and extremes, allow getting results with a
single query without having to run a number of them.</p>
<div class="block-50">
<h2>Key Features</h2>
<ul class="dashed smaller-font">
<li>True column-oriented storage</li>
<li>Vectorized query execution</li>
<li>Data compression</li>
<li>Parallel and distributed query execution</li>
<li>Real-time query processing and data ingestion</li>
<li>On-disk locality of reference</li>
<li>Cross-datacenter replication</li>
<li>High availability</li>
<li>SQL support</li>
<li>Local and distributed joins</li>
<li>Pluggable external dimension tables</li>
<li>Arrays and nested data types</li>
<li>Approximate query processing</li>
<li>Probabilistic data structures</li>
<li>Full support of IPv6</li>
<li>Features for web analytics</li>
<li>State-of-the-art algorithms</li>
<li>Detailed documentation</li>
<li>Clean documented code</li>
</ul>
</div>
<div class="block-50">
<h2>Applications</h2>
<ul class="dashed smaller-font">
<li>Web and App analytics</li>
<li>Advertising networks and RTB</li>
<li>Telecommunications</li>
<li>E-commerce</li>
<li>Information security</li>
<li>Monitoring and telemetry</li>
<li>Business intelligence</li>
<li>Online games</li>
<li>Internet of Things</li>
</ul>
</div>
<div class="clear"></div>
<h2 id="simple-and-handy">Simple and Handy</h2>
<p>ClickHouse streamlines all your data processing. Its easy to use: ingest all your structured data into the
system, and it&nbsp;is instantly available for reports. New columns for new properties or dimensions can be
easily added to the system at any time without slowing it&nbsp;down.</p>
<p>ClickHouse is simple and works out-of-the-box. As well as performing on hundreds of node clusters, this system
can be easily installed on a single server or even a virtual machine. No development experience or code-writing
skills are required to install ClickHouse.</p>
<h2 id="highly-reliable">Highly Reliable</h2>
<p>ClickHouse has been managing petabytes of data serving a number of highload mass audience services of Russias
leading search provider and one of Europes largest IT companies, <a href="https://www.yandex.com/company/"
rel="external nofollow">Yandex</a>.
Since 2012, ClickHouse has been providing robust database management for the companys <a
href="https://metrica.yandex.com/" rel="external nofollow">web analytics service</a>, comparison
shopping platform, email
service, online advertising platform, business intelligence and infrastructure monitoring.</p>
<p>ClickHouse is purely distributed system located on independent nodes, which has no single point of failure.</p>
<p>Software or hardware failures or misconfigurations do not result in loss of data. Instead of deleting "broken"
data, ClickHouse saves it&nbsp;or asks you what to do before a startup. All data are checksummed before every
read or write to disk or network. It&nbsp;is virtually impossible to delete data by accident.</p>
<p>ClickHouse offers flexible limits on query complexity and resource usage, which can be fine-tuned using settings.
It&nbsp;is possible to simultaneously serve both a number of high priority low-latency requests and some
long-running queries with lowered priority.</p>
<h2>Use Cases</h2>
<p>ClickHouse currently powers
<a href="https://metrica.yandex.com/" rel="external nofollow">Yandex.Metrica</a>, world's <a
href="http://w3techs.com/technologies/overview/traffic_analysis/all" rel="external nofollow">second
largest</a> web analytics
platform, with over 13 trillion database records and over 20 billion events a day, generating customized
reports on the fly directly from non-aggregated data.</p>
<p>Another example is <a
href="https://www.yandex.com/company/press_center/press_releases/2012/2012-04-10/"
rel="external nofollow">CERNs LHCb experiment</a>
to store and process metadata on 10bn events with over 1000 attributes per event registered
in 2011.</p>
<h2 id="quick-start">Quick Start</h2>
<p>System requirements: Linux, x86_64 with SSE 4.2.</p>
<p>Install packages for
<span class="distributive_not_selected" id="ubuntu_xenial">Ubuntu 16.04 Xenial</span>, <span
class="distributive_selected" id="ubuntu_trusty">Ubuntu 14.04 Trusty</span> or <span
class="distributive_not_selected" id="ubuntu_precise">Ubuntu 12.04 Precise</span>:
</p>
<code id="ubuntu-install">
<pre>
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv E0C56BD4 # optional
sudo mkdir -p /etc/apt/sources.list.d
echo "deb http://repo.yandex.ru/clickhouse/<span id="distributive">trusty</span> stable main" |
&nbsp;&nbsp;&nbsp;&nbsp;sudo tee /etc/apt/sources.list.d/clickhouse.list
sudo apt-get update
sudo apt-get install clickhouse-server-common clickhouse-client
sudo service clickhouse-server start
clickhouse-client
</pre>
</code>
<p>For other operating systems the easiest way to get started is using
<a href="https://hub.docker.com/r/yandex/clickhouse-server/" rel="external nofollow"
target="_blank">
official Docker images of ClickHouse</a>
. Alternatively you can build ClickHouse from <a
href="https://github.com/yandex/ClickHouse" rel="external nofollow"
target="_blank">sources</a>
according to the <a
href="https://github.com/yandex/ClickHouse/blob/master/doc/build.md" rel="external nofollow"
target="_blank">instruction</a>.</p>
<p>After installation proceed to <strong><a href="tutorial.html">tutorial</a></strong> or <strong><a href="reference_en.html">full
documentation</a></strong>.</p>
<h2 id="contacts">Contacts</h2>
<ul class="dashed">
<li>Ask any questions on <a href="https://stackoverflow.com/questions/tagged/clickhouse"
rel="external nofollow">Stack Overflow</a>.
</li>
<li>Discuss with real users in Telegram chat in <a href="https://telegram.me/clickhouse_en"
rel="external nofollow">English</a> or in <a
href="https://telegram.me/clickhouse_ru" rel="external nofollow">Russian</a>.
</li>
<li>Use <a href="https://groups.google.com/group/clickhouse" rel="external nofollow">Google Group</a> for
discussion.
</li>
<li>Or email ClickHouse team at Yandex:
<a id="feedback_email" href="">turn on JavaScript to see email address</a>.
</li>
</ul>
<h2>Like ClickHouse?</h2>
<p>Help to spread the word about it via <a rel="external nofollow" target="_blank" href="https://www.facebook.com/sharer.php?u=https://clickhouse.yandex">Facebook</a>,
<a rel="external nofollow" target="_blank" href="https://twitter.com/intent/tweet?url=https://clickhouse.yandex">Twitter</a> and
<a rel="external nofollow" target="_blank" href="https://www.linkedin.com/shareArticle?url=https://clickhouse.yandex">LinkedIn</a>!</p>
<p class="warranty">Software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.</p>
<p id="footer">&copy; 20162017 <a href="https://yandex.com/company/" rel="external nofollow">YANDEX</a> LLC</p>
</div>
<script type="text/javascript" src="https://yastatic.net/jquery/3.1.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
var name = $('#main-title').text().trim().toLowerCase();
var feedback_address = name + '-feedback' + '@yandex-team.com';
var feedback_email = $('#feedback_email');
feedback_email.attr('href', 'mailto:' + feedback_address);
feedback_email.html(feedback_address);
$("a[href^='#']").on('click', function (e) {
e.preventDefault();
var selector = $(e.target).attr('href');
var offset = 0;
if (selector) {
offset = $(selector).offset().top - $('#logo').height() * 1.5;
}
$('html, body').animate({
scrollTop: offset
}, 500);
});
var available_distributives = ['xenial', 'trusty', 'precise'];
available_distributives.forEach(function (name) {
$('#ubuntu_' + name).on('click', function () {
$('#distributive').html(name);
available_distributives.forEach(function (distr) {
$('#ubuntu_' + distr).attr('class', (name == distr) ? 'distributive_selected' : 'distributive_not_selected');
});
});
});
});
</script>
<!-- Yandex.Metrika counter -->
<script src="https://mc.yandex.ru/metrika/watch.js" type="text/javascript"></script>
<script type="text/javascript">
try {
var yaCounter18343495 = new Ya.Metrika({
id: 18343495,
webvisor: true,
clickmap: true,
trackLinks: true,
accurateTrackBounce: true,
trackHash: true
});
} catch (e) {
}
</script>
<noscript>
<div><img src="https://mc.yandex.ru/watch/18343495" style="position:absolute; left:-9999px;" alt=""/></div>
</noscript>
<!-- /Yandex.Metrika counter -->
</body>
</html>

10220
website/jquery.js vendored Normal file

File diff suppressed because it is too large Load Diff

BIN
website/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

Before

Width:  |  Height:  |  Size: 421 B

After

Width:  |  Height:  |  Size: 421 B

View File

@ -0,0 +1,21 @@
server {
listen 80;
listen [::]:80 default ipv6only=on;
root /usr/share/nginx/html;
index index.html index.htm;
server_name localhost;
location / {
try_files $uri $uri/ /index.html;
}
#error_page 404 /404.html;
#error_page 500 502 503 504 /50x.html;
#location = /50x.html {
# root /usr/share/nginx/www;
#}
}

37
website/nginx/nginx.conf Normal file
View File

@ -0,0 +1,37 @@
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 4096;
multi_accept on;
use epoll;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
keepalive_timeout 65;
gzip on;
gzip_comp_level 5;
gzip_min_length 256;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}

View File

@ -220,3 +220,10 @@ a:hover
.c13 { color: #ff54ff; }
.c14 { color: #54ffff; }
.c15 { color: #fff; }
.orange {
fill: #fc0;
}
.red {
fill: #f00
}

34
website/release.sh Executable file
View File

@ -0,0 +1,34 @@
#!/usr/bin/env bash
set -ex
BASE_DIR=$(dirname $(readlink -f $0))
cd "${BASE_DIR}"
gulp build
IMAGE="clickhouse/website"
if [[ -z "$1" ]]
then
TAG=$(head -c 8 /dev/urandom | xxd -p)
else
TAG="$1"
fi
FULL_NAME="${IMAGE}:${TAG}"
REMOTE_NAME="registry.yandex.net/${FULL_NAME}"
if [[ -z "$1" ]]
then
docker build -t "${FULL_NAME}" "${BASE_DIR}"
docker tag "${FULL_NAME}" "${REMOTE_NAME}"
docker push "${REMOTE_NAME}"
fi
QLOUD_ENDPOINT="https://platform.yandex-team.ru/api/v1"
QLOUD_PROJECT="clickhouse.clickhouse-website"
if [[ -z "$1" ]]
then
QLOUD_ENV="${QLOUD_PROJECT}.test"
else
QLOUD_ENV="${QLOUD_PROJECT}.prod"
fi
QLOUD_COMPONENT="${QLOUD_ENV}.nginx"
QLOUD_VERSION=$(curl -v -H "Authorization: OAuth ${QLOUD_TOKEN}" "${QLOUD_ENDPOINT}/environment/status/${QLOUD_ENV}" | python -c "import json; import sys; print json.loads(sys.stdin.read()).get('version')")
curl -v -H "Authorization: OAuth ${QLOUD_TOKEN}" -H "Content-Type: application/json" --data "{\"repository\": \"${REMOTE_NAME}\"}" "${QLOUD_ENDPOINT}/component/${QLOUD_COMPONENT}/${QLOUD_VERSION}/deploy" > /dev/null
echo ">>> Successfully deployed ${TAG} to ${QLOUD_ENV} <<<"

3
website/robots.txt Normal file
View File

@ -0,0 +1,3 @@
User-agent: *
Allow: /
Host: https://clickhouse.yandex

3
website/setup_gulp.sh Executable file
View File

@ -0,0 +1,3 @@
#!/usr/bin/env bash
set -ex
grep require gulpfile.js | awk -F\' '{print $2;}' | xargs npm install

830
website/tutorial.html Normal file
View File

@ -0,0 +1,830 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8"/>
<title>ClickHouse — quick start guide</title>
<link rel="shortcut icon" href="favicon.ico"/>
<meta name="description" content="Quick start guide to ClickHouse — open-source distributed column-oriented DBMS"/>
<meta name="keywords"
content="ClickHouse, DBMS, OLAP, relational, analytics, analytical, big data, open-source, SQL, web-analytics"/>
<style type="text/css">
@font-face {
font-family: 'Yandex Sans Text Web';
src: url(https://yastatic.net/adv-www/_/yy5JveR58JFkc97waf-xp0i6_jM.eot);
src: url(https://yastatic.net/adv-www/_/yy5JveR58JFkc97waf-xp0i6_jM.eot?#iefix) format('embedded-opentype'),
url(https://yastatic.net/adv-www/_/CYblzLEXzCqQIvrYs7QKQe2omRk.woff2) format('woff2'),
url(https://yastatic.net/adv-www/_/pUcnOdRwl83MvPPzrNomhyletnA.woff) format('woff'),
url(https://yastatic.net/adv-www/_/vNFEmXOcGYKJ4AAidUprHWoXrLU.ttf) format('truetype'),
url(https://yastatic.net/adv-www/_/0w7OcWZM_QLP8x-LQUXFOgXO6dE.svg#YandexSansTextWeb-Bold) format('svg');
font-weight: 700;
font-style: normal;
font-stretch: normal
}
@font-face {
font-family: 'Yandex Sans Text Web';
src: url(https://yastatic.net/adv-www/_/LI6l3L2RqcgxBe2pXmuUha37czQ.eot);
src: url(https://yastatic.net/adv-www/_/LI6l3L2RqcgxBe2pXmuUha37czQ.eot?#iefix) format('embedded-opentype'),
url(https://yastatic.net/adv-www/_/z3MYElcut0R2MF_Iw1RDNrstgYs.woff2) format('woff2'),
url(https://yastatic.net/adv-www/_/1jvKJ_-hCXl3s7gmFl-y_-UHTaI.woff) format('woff'),
url(https://yastatic.net/adv-www/_/9nzjfpCR2QHvK1EzHpDEIoVFGuY.ttf) format('truetype'),
url(https://yastatic.net/adv-www/_/gwyBTpxSwkFCF1looxqs6JokKls.svg#YandexSansTextWeb-Regular) format('svg');
font-weight: 400;
font-style: normal;
font-stretch: normal
}
@font-face {
font-family: 'Yandex Sans Text Web';
src: url(https://yastatic.net/adv-www/_/ayAFYoY8swgBLhq_I56tKj2JftU.eot);
src: url(https://yastatic.net/adv-www/_/ayAFYoY8swgBLhq_I56tKj2JftU.eot?#iefix) format('embedded-opentype'),
url(https://yastatic.net/adv-www/_/lGQcYklLVV0hyvz1HFmFsUTj8_0.woff2) format('woff2'),
url(https://yastatic.net/adv-www/_/f0AAJ9GJ4iiwEmhG-7PWMHk6vUY.woff) format('woff'),
url(https://yastatic.net/adv-www/_/4UDe4nlVvgEJ-VmLWNVq3SxCsA.ttf) format('truetype'),
url(https://yastatic.net/adv-www/_/EKLr1STNokPqxLAQa_RyN82pL98.svg#YandexSansTextWeb-Light) format('svg');
font-weight: 300;
font-style: normal;
font-stretch: normal
}
@font-face {
font-family: 'Yandex Sans Display Web';
src: url(https://yastatic.net/adv-www/_/H63jN0veW07XQUIA2317lr9UIm8.eot);
src: url(https://yastatic.net/adv-www/_/H63jN0veW07XQUIA2317lr9UIm8.eot?#iefix) format('embedded-opentype'),
url(https://yastatic.net/adv-www/_/sUYVCPUAQE7ExrvMS7FoISoO83s.woff2) format('woff2'),
url(https://yastatic.net/adv-www/_/v2Sve_obH3rKm6rKrtSQpf-eB7U.woff) format('woff'),
url(https://yastatic.net/adv-www/_/PzD8hWLMunow5i3RfJ6WQJAL7aI.ttf) format('truetype'),
url(https://yastatic.net/adv-www/_/lF_KG5g4tpQNlYIgA0e77fBSZ5s.svg#YandexSansDisplayWeb-Regular) format('svg');
font-weight: 400;
font-style: normal;
font-stretch: normal
}
@font-face {
font-family: 'Yandex Sans Display Web';
src: url(https://yastatic.net/adv-www/_/g8_MyyKVquSZ3xEL6tarK__V9Vw.eot);
src: url(https://yastatic.net/adv-www/_/g8_MyyKVquSZ3xEL6tarK__V9Vw.eot?#iefix) format('embedded-opentype'),
url(https://yastatic.net/adv-www/_/LGiRvlfqQHlWR9YKLhsw5e7KGNA.woff2) format('woff2'),
url(https://yastatic.net/adv-www/_/40vXwNl4eYYMgteIVgLP49dwmfc.woff) format('woff'),
url(https://yastatic.net/adv-www/_/X6zG5x_wO8-AtwJ-vDLJcKC5228.ttf) format('truetype'),
url(https://yastatic.net/adv-www/_/ZKhaR0m08c8CRRL77GtFKoHcLYA.svg#YandexSansDisplayWeb-Light) format('svg');
font-weight: 300;
font-style: normal;
font-stretch: normal
}
body {
background: #fff;
font: 300 12pt/150% 'Yandex Sans Text Web', Arial, sans-serif;
}
.page {
width: 900px;
margin: auto;
}
h1 {
font-family: 'Yandex Sans Display Web', Arial, sans-serif;
font-size: 100px;
font-weight: normal;
margin-top: 100px;
margin-bottom: 0;
text-align: center;
padding-top: 27px;
}
.title_link, .title_link:active, .title_link:visited, .title_link:link, .title_link:hover {
text-decoration: none;
color: #000;
}
h2 {
font: normal 50px 'Yandex Sans Display Web', Arial, sans-serif;
text-align: center;
margin-top: 35px;
margin-bottom: 50px;
}
h3 {
font: normal 24px 'Yandex Sans Display Web', Arial, sans-serif;
margin-top: 36px;
}
a:link, a:visited {
color: #08f;
text-decoration: none;
}
a:hover, a:active {
color: #f00;
text-decoration: underline;
}
.footer {
text-align: right;
margin-top: 40px;
border-top: 1px solid #EEE;
padding: 10px 0 0;
color: #888;
font-size: 10pt;
}
pre {
font: 13px/18px monospace, "Courier New";
display: block;
border-left: 5px solid #ffdb4d;
padding: 5px 10px;
background-color: #FFF8E8;
}
.spoiler {
margin-bottom: 10px;
}
.spoiler_body {
display: none;
}
.spoiler_title {
color: #08f;
border-bottom: 1px dotted #08f;
}
.spoiler_title:hover {
cursor: pointer;
color: #f00;
border-bottom: 1px dashed #f00;
text-decoration: none;
}
.tip {
background-color: #EEE;
border: 1px solid #EEE;
padding: 5px 10px 5px 10px;
}
.tip b {
font-size: 150%;
color: #888;
}
.warranty {
font-size: 10pt;
color: #888;
line-height: 150%;
}
.orange {
fill: #fc0;
}
.red {
fill: #f00
}
</style>
</head>
<body>
<div class="page">
<div>
<div style="float: left; margin-right: -100%; margin-top: 0; margin-left: 3px;">
<a href="/">
<svg xmlns="http://www.w3.org/2000/svg" width="90" height="80" viewBox="0 0 9 8">
<path class="red" d="M0,7 h1 v1 h-1 z"></path>
<path class="orange" d="M0,0 h1 v7 h-1 z"></path>
<path class="orange" d="M2,0 h1 v8 h-1 z"></path>
<path class="orange" d="M4,0 h1 v8 h-1 z"></path>
<path class="orange" d="M6,0 h1 v8 h-1 z"></path>
<path class="orange" d="M8,3.25 h1 v1.5 h-1 z"></path>
</svg>
</a>
</div>
<h1 id="main_title"><a class="title_link" href="/">ClickHouse</a></h1>
<h2>Tutorial</h2>
</div>
<p>Let's get started with sample dataset from open sources. We will use USA civil flights data since 1987 till 2015.
It's hard to call this sample a Big Data (contains 166 millions rows, 63 Gb of uncompressed data) but this
allows us to quickly get to work. Dataset is available for download <a href="https://yadi.sk/d/pOZxpa42sDdgm">here</a>.
Also you may download it from the original datasource <a
href="https://github.com/yandex/ClickHouse/raw/master/doc/example_datasets/1_ontime.txt"
rel="external nofollow">as described
here</a>.</p>
<p>Firstly we will deploy ClickHouse to a single server. Below that we will also review the process of deployment to
a cluster with support for sharding and replication.</p>
<p>On Ubuntu and Debian Linux ClickHouse can be installed from <a href="/#download">packages</a>.
For other Linux distributions you can <a href="https://github.com/yandex/ClickHouse/blob/master/doc/build.md"
rel="external nofollow">compile
ClickHouse from sources</a> and then install.</p>
<p><b>clickhouse-client</b> package contains <a
href="/reference_en.html#Command-line%20client">clickhouse-client</a> application —
interactive ClickHouse client. <b>clickhouse-server-base</b> contains a clickhouse-server binary file. <b>clickhouse-server-common</b>
— contains config files for the clickhouse-server.</p>
<p>Server config files are located in /etc/clickhouse-server/. Before getting to work please notice the <b>path</b>
element in config. <b>Path</b>&nbsp;determines the location for data storage. It's not really handy to directly
edit <b>config.xml</b> file considering package updates. Recommended way is to override the config elements in
<a href="/reference_en.html#Configuration%20files">files of config.d directory</a>.
Also you may want to <a href="/reference_en.html#Access%20rights">set up access
rights</a> at the start.</p>
<p><b>clickhouse-server</b> won't be launched automatically after package installation. It won't be automatically
restarted after updates either. Start the server with:
<pre>sudo service clickhouse-server start</pre>
Default location for server logs is /var/log/clickhouse-server/
Server is ready to handle client conections once "Ready&nbsp;for&nbsp;connections" message was logged.</p>
<p>Use <b>clickhouse-client</b> to connect to the server.</p>
<div class="spoiler"><a class="spoiler_title">Tips for clickhouse-client</a>
<div class="spoiler_body">
Interactive mode:
<pre>
clickhouse-client
clickhouse-client --host=... --port=... --user=... --password=...
</pre>
Enable multiline queries:
<pre>
clickhouse-client -m
clickhouse-client --multiline
</pre>
Run queries in batch-mode:
<pre>
clickhouse-client --query='SELECT 1'
echo 'SELECT 1' | clickhouse-client
</pre>
Inser data from file of a specified format:
<pre>
clickhouse-client --query='INSERT INTO table VALUES' &lt; data.txt
clickhouse-client --query='INSERT INTO table FORMAT TabSeparated' &lt; data.tsv
</pre>
</div>
</div>
<h3>Create table for sample dataset</h3>
<div class="spoiler"><a class="spoiler_title">Create table query</a>
<div class="spoiler_body">
<pre>
$ clickhouse-client --multiline
ClickHouse client version 0.0.53720.
Connecting to localhost:9000.
Connected to ClickHouse server version 0.0.53720.
:) CREATE TABLE ontime
(
Year UInt16,
Quarter UInt8,
Month UInt8,
DayofMonth UInt8,
DayOfWeek UInt8,
FlightDate Date,
UniqueCarrier FixedString(7),
AirlineID Int32,
Carrier FixedString(2),
TailNum String,
FlightNum String,
OriginAirportID Int32,
OriginAirportSeqID Int32,
OriginCityMarketID Int32,
Origin FixedString(5),
OriginCityName String,
OriginState FixedString(2),
OriginStateFips String,
OriginStateName String,
OriginWac Int32,
DestAirportID Int32,
DestAirportSeqID Int32,
DestCityMarketID Int32,
Dest FixedString(5),
DestCityName String,
DestState FixedString(2),
DestStateFips String,
DestStateName String,
DestWac Int32,
CRSDepTime Int32,
DepTime Int32,
DepDelay Int32,
DepDelayMinutes Int32,
DepDel15 Int32,
DepartureDelayGroups String,
DepTimeBlk String,
TaxiOut Int32,
WheelsOff Int32,
WheelsOn Int32,
TaxiIn Int32,
CRSArrTime Int32,
ArrTime Int32,
ArrDelay Int32,
ArrDelayMinutes Int32,
ArrDel15 Int32,
ArrivalDelayGroups Int32,
ArrTimeBlk String,
Cancelled UInt8,
CancellationCode FixedString(1),
Diverted UInt8,
CRSElapsedTime Int32,
ActualElapsedTime Int32,
AirTime Int32,
Flights Int32,
Distance Int32,
DistanceGroup UInt8,
CarrierDelay Int32,
WeatherDelay Int32,
NASDelay Int32,
SecurityDelay Int32,
LateAircraftDelay Int32,
FirstDepTime String,
TotalAddGTime String,
LongestAddGTime String,
DivAirportLandings String,
DivReachedDest String,
DivActualElapsedTime String,
DivArrDelay String,
DivDistance String,
Div1Airport String,
Div1AirportID Int32,
Div1AirportSeqID Int32,
Div1WheelsOn String,
Div1TotalGTime String,
Div1LongestGTime String,
Div1WheelsOff String,
Div1TailNum String,
Div2Airport String,
Div2AirportID Int32,
Div2AirportSeqID Int32,
Div2WheelsOn String,
Div2TotalGTime String,
Div2LongestGTime String,
Div2WheelsOff String,
Div2TailNum String,
Div3Airport String,
Div3AirportID Int32,
Div3AirportSeqID Int32,
Div3WheelsOn String,
Div3TotalGTime String,
Div3LongestGTime String,
Div3WheelsOff String,
Div3TailNum String,
Div4Airport String,
Div4AirportID Int32,
Div4AirportSeqID Int32,
Div4WheelsOn String,
Div4TotalGTime String,
Div4LongestGTime String,
Div4WheelsOff String,
Div4TailNum String,
Div5Airport String,
Div5AirportID Int32,
Div5AirportSeqID Int32,
Div5WheelsOn String,
Div5TotalGTime String,
Div5LongestGTime String,
Div5WheelsOff String,
Div5TailNum String
)
ENGINE = MergeTree(FlightDate, (Year, FlightDate), 8192);
</pre>
</div>
</div>
<p>Now we have a table of <a href="/reference_en.html#MergeTree">MergeTree type</a>.
MergeTree table type is recommended for usage in production. Table of this kind has a primary key used for
incremental sort of table data. This allows fast execution of queries in ranges of a primary key.</p>
<p><b>Note</b>
We store ad network banners impressions logs in ClickHouse. Each table entry looks like:
<source>
[Advertiser ID, Impression ID, attribute1, attribute2, &hellip;]</pre>
Let assume that our aim is to provide a set of reports for each advertiser. Common and frequently demanded query
would be to count impressions for a specific Advertiser ID. This means that table primary key should start with
<source>
Advertiser ID</pre>. In this case ClickHouse needs to read smaller amount of data to perform the query for a
given
<source>
Advertiser ID</pre>.
</p>
<h3>Load data</h3>
<pre>xz -v -c -d &lt; ontime.csv.xz | clickhouse-client --query="INSERT INTO ontime FORMAT CSV"</pre>
<p>ClickHouse INSERT query allows to load data in any <a href="/reference_en.html#Formats">supported
format</a>. Data load requires just O(1) RAM consumption. INSERT query can receive any data volume as input.
It's strongly recommended to insert data with <a
href="/reference_en.html#Performance%20on%20data%20insertion.">not too small
size blocks</a>. Notice that insert of blocks with size up to max_insert_block_size (= 1&nbsp;048&nbsp;576
rows by default) is an atomic operation: data block will be inserted completely or not inserted at all. In case
of disconnect during insert operation you may not know if the block was inserted successfully. To achieve
exactly-once semantics ClickHouse supports idempotency for <a
href="/reference_en.html#Data%20replication">replicated tables</a>. This means
that you may retry insert of the same data block (possibly on a different replicas) but this block will be
inserted just once. Anyway in this guide we will load data from our localhost so we may not take care about data
blocks generation and exactly-once semantics.</p>
<p>INSERT query into tables of MergeTree type is non-blocking (so does a SELECT query). You can execute SELECT
queries right after of during insert operation.</p>
<p>Our sample dataset is a bit not optimal. There are two reasons.</p>
<p>The first is that String data type is used in cases when <a
href="/reference_en.html#Enum">Enum</a> or numeric type would fit best.</p>
<p class="tip"><b></b> When set of possible values is determined and known to be small. (E.g. OS name, browser
vendors etc.) it's&nbsp;recommended to use Enums or numbers to improve performance.
When set of possible values is not limited (search&nbsp;query, URL, etc.) just go ahead with String.</p>
<p>The second is that dataset contains redundant fields like Year, Quarter, Month, DayOfMonth, DayOfWeek. In fact a
single FlightDate would be enough. Most likely they have been added to improve performance for other DBMS'es
which DateTime handling functions may be not efficient.</p>
<p class="tip"><b></b> ClickHouse <a
href="/reference_en.html#Functions%20for%20working%20with%20dates%20and%20times">functions
for operating with DateTime fields</a> are well-optimized so such redundancy is not required. Anyway much
columns is not a reason to worry — ClickHouse is a <a href="https://en.wikipedia.org/wiki/Column-oriented_DBMS">column-oriented
DBMS</a>. This allows you to have as much fields as you need. Hundreds of columns in a table is fine for
ClickHouse.</p>
<h3>Querying the sample dataset</h3>
<p>Here are some examples of the queries from our test data.</p>
<ul>
<li>
<div class="spoiler"><a class="spoiler_title">the most popular destinations in 2015;</a>
<div class="spoiler_body">
<pre>
SELECT
OriginCityName,
DestCityName,
count(*) AS flights,
bar(flights, 0, 20000, 40)
FROM ontime WHERE Year = 2015 GROUP BY OriginCityName, DestCityName ORDER BY flights DESC LIMIT 20
</pre>
<img src="https://habrastorage.org/files/a85/18a/200/a8518a200d6d405a95ee80ea1c8e1c90.png"/>
<pre>
SELECT
OriginCityName &lt; DestCityName ? OriginCityName : DestCityName AS a,
OriginCityName &lt; DestCityName ? DestCityName : OriginCityName AS b,
count(*) AS flights,
bar(flights, 0, 40000, 40)
FROM ontime WHERE Year = 2015 GROUP BY a, b ORDER BY flights DESC LIMIT 20
</pre>
<img src="https://habrastorage.org/files/d35/78d/b55/d3578db55e304bd7b5eba818abdb53f5.png"/></div>
</div>
</li>
<li>
<div class="spoiler"><a class="spoiler_title">the most popular cities of departure;</a>
<div class="spoiler_body">
<pre>
SELECT OriginCityName, count(*) AS flights
FROM ontime GROUP BY OriginCityName ORDER BY flights DESC LIMIT 20
</pre>
<img src="https://habrastorage.org/files/ef4/141/f34/ef4141f348234773a5349c4bd3e8f804.png"/></div>
</div>
</li>
<li>
<div class="spoiler"><a class="spoiler_title">cities of departure which offer maximum variety of
destinations;</a>
<div class="spoiler_body">
<pre>
SELECT OriginCityName, uniq(Dest) AS u
FROM ontime GROUP BY OriginCityName ORDER BY u DESC LIMIT 20
</pre>
<img src="https://habrastorage.org/files/240/9f4/9d1/2409f49d11fb4aa1b8b5ff34cf9ca75d.png"/></div>
</div>
</li>
<li>
<div class="spoiler"><a class="spoiler_title">flight delay dependence on the day of week;</a>
<div class="spoiler_body">
<pre>
SELECT DayOfWeek, count() AS c, avg(DepDelay &gt; 60) AS delays
FROM ontime GROUP BY DayOfWeek ORDER BY DayOfWeek
</pre>
<img src="https://habrastorage.org/files/885/e50/793/885e507930e34b7c8f788d25e7ca2bcf.png"/></div>
</div>
</li>
<li>
<div class="spoiler"><a class="spoiler_title">cities of departure with most frequent delays for 1 hour or
longer;</a>
<div class="spoiler_body">
<pre>
SELECT OriginCityName, count() AS c, avg(DepDelay &gt; 60) AS delays
FROM ontime
GROUP BY OriginCityName
HAVING c &gt; 100000
ORDER BY delays DESC
LIMIT 20
</pre>
<img src="https://habrastorage.org/files/ac2/926/56d/ac292656d03946d0aba35c75783a31f2.png"/></div>
</div>
</li>
<li>
<div class="spoiler"><a class="spoiler_title">flights of maximum duration;</a>
<div class="spoiler_body">
<pre>
SELECT OriginCityName, DestCityName, count(*) AS flights, avg(AirTime) AS duration
FROM ontime
GROUP BY OriginCityName, DestCityName
ORDER BY duration DESC
LIMIT 20
</pre>
<img src="https://habrastorage.org/files/7b3/c2e/685/7b3c2e685832439b8c373bf2015131d2.png"/></div>
</div>
</li>
<li>
<div class="spoiler"><a class="spoiler_title">distribution of arrival time delays split by aircompanies;</a>
<div class="spoiler_body">
<pre>
SELECT Carrier, count() AS c, round(quantileTDigest(0.99)(DepDelay), 2) AS q
FROM ontime GROUP BY Carrier ORDER BY q DESC
</pre>
<img src="https://habrastorage.org/files/49c/332/e3d/49c332e3d93146ba8f46beef6b2b02b0.png"/></div>
</div>
</li>
<li>
<div class="spoiler"><a class="spoiler_title">aircompanies who stopped flights operation;</a>
<div class="spoiler_body">
<pre>
SELECT Carrier, min(Year), max(Year), count()
FROM ontime GROUP BY Carrier HAVING max(Year) &lt; 2015 ORDER BY count() DESC
</pre>
<img src="https://habrastorage.org/files/249/56f/1a2/24956f1a2efc48d78212586958aa036c.png"/></div>
</div>
</li>
<li>
<div class="spoiler"><a class="spoiler_title">most trending destination cities in 2015;</a>
<div class="spoiler_body">
<pre>
SELECT
DestCityName,
sum(Year = 2014) AS c2014,
sum(Year = 2015) AS c2015,
c2015 / c2014 AS diff
FROM ontime
WHERE Year IN (2014, 2015)
GROUP BY DestCityName
HAVING c2014 &gt; 10000 AND c2015 &gt; 1000 AND diff &gt; 1
ORDER BY diff DESC
</pre>
<img src="https://habrastorage.org/files/f31/32f/4d1/f3132f4d1c0d42eab26d9111afe7771a.png"/></div>
</div>
</li>
<li>
<div class="spoiler"><a class="spoiler_title">destination cities with maximum popularity-season
dependency.</a>
<div class="spoiler_body">
<pre>
SELECT
DestCityName,
any(total),
avg(abs(monthly * 12 - total) / total) AS avg_month_diff
FROM
(
SELECT DestCityName, count() AS total
FROM ontime GROUP BY DestCityName HAVING total &gt; 100000
)
ALL INNER JOIN
(
SELECT DestCityName, Month, count() AS monthly
FROM ontime GROUP BY DestCityName, Month HAVING monthly &gt; 10000
)
USING DestCityName
GROUP BY DestCityName
ORDER BY avg_month_diff DESC
LIMIT 20
</pre>
<img src="https://habrastorage.org/files/26b/2c7/aae/26b2c7aae21a4c76800cb1c7a33a374d.png"/></div>
</div>
</li>
</ul>
<h3>ClickHouse deployment to cluster</h3>
<p>ClickHouse cluster is a homogenous cluster. Steps to set up:
<ol>
<li>Install ClickHouse server on all machines of the cluster</li>
<li>Set up cluster configs in configuration file</li>
<li>Create local tables on each instance</li>
<li>Create a <a href="/reference_en.html#Distributed">Distributed table</a></li>
</ol>
</p>
<p><a href="/reference_en.html#Distributed">Distributed-table</a> is actually a kind of
"view" to local tables of ClickHouse cluster. SELECT query from a distributed table will be executed using
resources of all cluster's shards. You may specify configs for multiple clusters and create multiple
Distributed-tables providing views to different clusters.</p>
<div class="spoiler"><a class="spoiler_title">Config for cluster of three shards. Each shard stores data on a single
replica</a>
<div class="spoiler_body">
<pre>
&lt;remote_servers&gt;
&lt;perftest_3shards_1replicas&gt;
&lt;shard&gt;
&lt;replica&gt;
&lt;host&gt;example-perftest01j.yandex.ru&lt;/host&gt;
&lt;port&gt;9000&lt;/port&gt;
&lt;/replica&gt;
&lt;/shard&gt;
&lt;shard&gt;
&lt;replica&gt;
&lt;host&gt;example-perftest02j.yandex.ru&lt;/host&gt;
&lt;port&gt;9000&lt;/port&gt;
&lt;/replica&gt;
&lt;/shard&gt;
&lt;shard&gt;
&lt;replica&gt;
&lt;host&gt;example-perftest03j.yandex.ru&lt;/host&gt;
&lt;port&gt;9000&lt;/port&gt;
&lt;/replica&gt;
&lt;/shard&gt;
&lt;/perftest_3shards_1replicas&gt;
&lt;/remote_servers&gt;
</pre>
</div>
</div>
Creating a local table:
<pre>CREATE TABLE ontime_local (...) ENGINE = MergeTree(FlightDate, (Year, FlightDate), 8192);</pre>
Creating a distributed table providing a view into local tables of the cluster:
<pre>CREATE TABLE ontime_all AS ontime_local
ENGINE = Distributed(perftest_3shards_1replicas, default, ontime_local, rand());</pre>
<p>You can create a Distributed table on all machines in the cluster. This would allow to run distributed queries on
any machine of the cluster. Besides distributed table you can also use <a
href="/reference_en.html#remote">*remote* table function</a>.</p>
<p>Let's run <a href="/reference_en.html#INSERT">INSERT SELECT</a> into Distributed table
to spread the table to multiple servers.</p>
<pre>INSERT INTO ontime_all SELECT * FROM ontime;</pre>
<p class="tip"><b></b> Worth to notice that the approach given above wouldn't fit for sharding of large
tables.<br/>Please use <a href="/reference_en.html#Resharding">built-in sharding
feature</a>.</p>
<p>As you could expect heavy queries are executed N times faster being launched on 3 servers instead of one.</p>
<div class="spoiler"><a class="spoiler_title">See here</a>
<div class="spoiler_body">
<img src="https://habrastorage.org/files/ece/020/129/ece020129fdf4a18a6e75daf2e699cb9.png"/>
<p>You may have noticed that quantiles calculation are slightly different. This happens due to <a
href="https://github.com/tdunning/t-digest/raw/master/docs/t-digest-paper/histo.pdf">t-digest</a>
algorithm implementation which is non-deterministic — it depends on the order of data processing.</p>
</div>
</div>
<p>In this case we have used a cluster with 3 shards each contains a single replica.</p>
<p>To provide for resilience in production environment we recommend that each shard should contain 2-3 replicas
distributed between multiple data-centers. Note that ClickHouse supports unlimited number of replicas.</p>
<div class="spoiler"><a class="spoiler_title">Config for cluster of one shard containing three replicas</a>
<div class="spoiler_body">
<pre>
&lt;remote_servers&gt;
...
&lt;perftest_1shards_3replicas&gt;
&lt;shard&gt;
&lt;replica&gt;
&lt;host&gt;example-perftest01j.yandex.ru&lt;/host&gt;
&lt;port&gt;9000&lt;/port&gt;
&lt;/replica&gt;
&lt;replica&gt;
&lt;host&gt;example-perftest02j.yandex.ru&lt;/host&gt;
&lt;port&gt;9000&lt;/port&gt;
&lt;/replica&gt;
&lt;replica&gt;
&lt;host&gt;example-perftest03j.yandex.ru&lt;/host&gt;
&lt;port&gt;9000&lt;/port&gt;
&lt;/replica&gt;
&lt;/shard&gt;
&lt;/perftest_1shards_3replicas&gt;
&lt;/remote_servers&gt;
</pre>
</div>
</div>
<p>To enable replication <a href="http://zookeeper.apache.org/">ZooKeeper</a> is required. ClickHouse will take care
of data consistency on all replicas and run restore procedure after failure automatically. It's recommended to
deploy ZooKeeper cluster to separate servers.</p>
<p>ZooKeeper is not a requirement — in some simple cases you can duplicate the data by writing it into all the
replicas from your application code. This approach is not recommended — in this case ClickHouse is not able to
guarantee data consistency on all replicas. This remains the responsibility of your application.</p>
<div class="spoiler"><a class="spoiler_title">Set ZooKeeper locations in configuration file</a>
<div class="spoiler_body">
<pre>
&lt;zookeeper-servers&gt;
&lt;node&gt;
&lt;host&gt;zoo01.yandex.ru&lt;/host&gt;
&lt;port&gt;2181&lt;/port&gt;
&lt;/node&gt;
&lt;node&gt;
&lt;host&gt;zoo02.yandex.ru&lt;/host&gt;
&lt;port&gt;2181&lt;/port&gt;
&lt;/node&gt;
&lt;node&gt;
&lt;host&gt;zoo03.yandex.ru&lt;/host&gt;
&lt;port&gt;2181&lt;/port&gt;
&lt;/node&gt;
&lt;/zookeeper-servers&gt;
</pre>
</div>
</div>
<p>Also we need to set macros for identifying shard and replica — it will be used on table creation</p>
<pre>
&lt;macros&gt;
&lt;shard&gt;01&lt;/shard&gt;
&lt;replica&gt;01&lt;/replica&gt;
&lt;/macros&gt;
</pre>
<p>If there are no replicas at the moment on replicated table creation — a new first replica will be instantiated.
If there are already live replicas — new replica will clone the data from existing ones. You have an option to
create all replicated tables first and that insert data to it. Another option is to create some replicas and add
the others after or during data insertion.</p>
<pre>
CREATE TABLE ontime_replica (...)
ENGINE = ReplicatedMergeTree(
'/clickhouse_perftest/tables/{shard}/ontime',
'{replica}',
FlightDate,
(Year, FlightDate),
8192);
</pre>
<p>Here we use <a href="/reference_en.html#ReplicatedMergeTree">ReplicatedMergeTree</a>
table type. In parameters we specify ZooKeeper path containing shard and replica identifiers.</p>
<pre>INSERT INTO ontime_replica SELECT * FROM ontime;</pre>
<p>Replication operates in multi-master mode. Data can be loaded into any replica — it will be synced with other
instances automatically. Replication is asynchronous so at a given moment of time not all replicas may contain
recently inserted data. To allow data insertion at least one replica should be up. Others will sync up data and
repair consistency once they will become active again. Please notice that such scheme allows for the possibility
of just appended data loss.</p>
<h3>Feedback</h3>
<p>Ask any questions on <a href="https://stackoverflow.com/questions/tagged/clickhouse" rel="external nofollow">Stack
Overflow</a>.</p>
<p>Discuss with real users in Telegram chat in <a href="https://telegram.me/clickhouse_en" rel="external nofollow">English</a>
or in <a
href="https://telegram.me/clickhouse_ru" rel="external nofollow">Russian</a>.</p>
<p>Use <a href="https://groups.google.com/group/clickhouse" rel="external nofollow">Google Group</a> for discussion.
</p>
<p>Or send private message to developers:
<a id="feedback_email" href="">turn on JavaScript to see email address</a>.
</p>
<p class="warranty">Software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
either express or implied.</p>
<p class="footer">&copy; 20162017 <a href="https://yandex.com/company/" rel="external nofollow">YANDEX</a> LLC</p>
</div>
<script type="text/javascript" src="https://yastatic.net/jquery/3.1.1/jquery.min.js"></script>
<script type="text/javascript">
function getParams() {
var matches = document.cookie.match(/yandex_login=([\w\-]+)/);
return (matches && matches.length == 2) ? {"login": matches[1]} : {};
}
$('.spoiler_title').click(function () {
$(this).next('.spoiler_body').toggle(100);
});
var name = document.getElementById('main_title').textContent.trim().toLowerCase();
var feedback_address = name + '-feedback' + '@yandex-team.com';
var feedback_email = document.getElementById('feedback_email');
feedback_email.setAttribute('href', 'mailto:' + feedback_address);
feedback_email.textContent = feedback_address;
</script>
<!-- Yandex.Metrika counter -->
<script src="https://mc.yandex.ru/metrika/watch.js" type="text/javascript"></script>
<script type="text/javascript">
try {
var yaCounter18343495 = new Ya.Metrika({
id: 18343495,
webvisor: true,
clickmap: true,
trackLinks: true,
accurateTrackBounce: true,
trackHash: true,
params: getParams()
});
} catch (e) {
}
</script>
<noscript>
<div><img src="https://mc.yandex.ru/watch/18343495" style="position:absolute; left:-9999px;" alt=""/></div>
</noscript>
<!-- /Yandex.Metrika counter -->
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 724 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 810 B