什么是ClickHouse?
ClickHouse 是面向 OLAP 的分布式列式 DBMS.
在“正常”的面向行的DBMS中,數據按順序進行存儲:
5123456789123456789? ? 1? ? ? Eurobasket - Greece - Bosnia and Herzegovina - example.com? ? ? 1? ? ? 2011-09-01 01:03:02? ? 6274717? 1294101174? ? ? 11409? 612345678912345678? ? ? 0? ? ? 33? ? ? 6? ? ? http://www.example.com/basketball/team/123/match/456789.html http://www.example.com/basketball/team/123/match/987654.html? ? ? 0? ? ? 1366? ? 768? ? 32? ? ? 10? ? ? 3183? ? ? 0? ? ? 0? ? ? 13? ? ? 0\0? ? 1? ? ? 1? ? ? 0? ? ? 0? ? ? ? ? ? ? ? ? ? ? 2011142 -1? ? ? 0? ? ? ? ? ? ? 0? ? ? 01321? ? 613? ? 660? ? 2011-09-01 08:01:17? ? 0? ? ? 0? ? ? 0? ? ? 0? ? ? utf-8? 1466? ? 0? ? ? 0? ? ? 0? ? ? 5678901234567890123? ? ? ? ? ? ? 277789954? ? ? 0? ? ? 0? ? ? 0? ? ? 0? ? ? 0
5234985259563631958? ? 0? ? ? Consulting, Tax assessment, Accounting, Law? ? ? 1? ? ? 2011-09-01 01:03:02? ? 6320881? 2111222333? ? ? 213? ? 6458937489576391093? ? 0? ? ? 3? ? ? 2? ? ? http://www.example.ru/? ? ? ? 0? ? ? 800? ? 600? ? ? 16? ? ? 10? ? ? 2? ? ? 153.1? 0? ? ? 0? ? ? 10? ? ? 63? ? ? 1? ? ? 1? ? ? 0? ? ? 0? ? ? ? ? ? ? ? ? ? ? 2111678 000? ? ? 0? ? ? 588? ? 368? ? 240? ? 2011-09-01 01:03:17? ? 4? ? ? 0? ? ? 60310? 0? ? ? windows-1251? ? 1466? ? 0? ? ? 000? ? ? ? ? ? ? 778899001? ? ? 0? ? ? 0? ? ? 0? ? ? 0? ? ? 0
...
換句話說,與一行相關的所有值都被存儲在一起。面向行的DBMS主要有MySQL,Postgres,MS SQL Server等等。
在面向列的DBMS中,數據存儲如下:
WatchID:5385521489354350662? ? 5385521490329509958? ? 5385521489953706054? ? 5385521490476781638? ? 5385521490583269446? ? 5385521490218868806? ? 5385521491437850694? 5385521491090174022? ? ? 5385521490792669254? ? 5385521490420695110? ? 5385521491532181574? ? 5385521491559694406? ? 5385521491459625030? ? 5385521492275175494? 5385521492781318214? ? ? 5385521492710027334? ? 5385521492955615302? ? 5385521493708759110? ? 5385521494506434630? ? 5385521493104611398
JavaEnable:1? ? ? 0? ? ? 1? ? ? 0? ? ? 0? ? ? 0? ? ? 1? ? ? 0? ? ? 1? ? ? 1? ? ? 1? ? ? 1? ? ? 1? ? ? 1? ? ? 0? ? ? 1? ? ? 0? ? ? 0? ? ? 1? ? ? 1
Title:Yandex? Announcements - Investor Relations - Yandex? ? Yandex — Contact us — Moscow? ? Yandex — Mission? ? ? ? Ru? ? ? Yandex — History — History of Yandex? ? Yandex Financial Releases - Investor Relations - Yandex Yandex — Locations? ? ? Yandex Board of Directors - Corporate Governance - Yandex? ? ? Yandex — Technologies
GoodEvent:1? ? ? 1? ? ? 1? ? ? 1? ? ? 1? ? ? 1? ? ? 1? ? ? 1? ? ? 1? ? ? 1? ? ? 1? ? ? 1? ? ? 1? ? ? 1? ? ? 1? ? ? 1? ? ? 1? ? ? 1? ? ? 1? ? ? 1
EventTime:2016-05-18 05:19:20? ? 2016-05-18 08:10:20? ? 2016-05-18 07:38:00? ? 2016-05-18 01:13:08? ? 2016-05-18 00:04:06? ? 2016-05-18 04:21:30? ? 2016-05-18 00:34:16? ? 2016-05-18 07:35:49? ? 2016-05-18 11:41:59? ? 2016-05-18 01:13:32...
這些示例僅顯示數據排列的順序。不同列的值分開存儲,同一列的數據一起存儲。例如,面向列的DBMS:Vertica,Paraccel(Actian Matrix)(Amazon Redshift),Sybase IQ,Exasol,Infobright,InfiniDB,MonetDB(VectorWise)(Actian Vector),LucidDB,SAP HANA,Google Dremel,Google PowerDrill,Druid ,kdb +等。
存儲數據的不同存儲順序更適合于不同的應用場景。數據訪問場景指的是執行什么查詢,多長時間查詢,每種類型的查詢讀取多少數據 - 行,列和字節;寫取和更新數據之間的關系;數據的大小以及它在本地的使用情況;是否使用交易處理,以及它們是如何隔離的;數據同步和邏輯完整性的要求;每類查詢的延遲和吞吐量要求等等。
系統上的負載越高,場景化的系統定制就越重要,定制化就越具體。沒有一個系統能夠適用于截然不同的應用場景。如果一個系統可以適應多種場景,那么在高負載情況下,系統處理所有場景表現都會很差,或者僅其中一種場景表現良好。
對于OLAP(聯機分析處理)方案,將會有如下幾種應用場景:
- 絕大多數請求是以讀為主。
- 數據以相當大的批次(> 1000行)進行更新,而不是單行更新;或者根本不更新。
- 數據被添加到數據庫,基本不怎么修改。
- 對于讀取,大量的數據從數據庫中抽取出來,但只有列的一個子集。
- 表是“寬的”,這意味著它們包含大量的列。
- 查詢相對較少(通常每臺服務器數百個查詢或更少)。
- 對于簡單的查詢,允許大約50 ms的延遲。
- 列值相當小 - 數字和短字符串(例如,每個URL 60個字節)。
- 處理單個查詢時需要高吞吐量(每臺服務器每秒高達數十億行)。
- 無事務處理。
- 數據一致性要求低- 每個查詢有一個大表,其他所有的表都是小表。
- 查詢結果顯著小于源數據。也就是說,數據被過濾或聚合。結果可以放在單個服務器的內存中。
很容易看出,OLAP方案與其他常見方案(如OLTP或Key-Value訪問)有很大不同。所以,如果你想獲得不錯的表現,嘗試使用OLTP或Key-Value DB來處理分析查詢是沒有意義的。例如,如果您嘗試使用MongoDB或Elliptics進行分析,與OLAP數據庫相比,您的性能會很差。
面向列的數據庫更適合于OLAP方案(對于大多數查詢,處理速度至少提高了100倍),原因如下:
1.對于I/O
1.1 對于分析查詢,只需要讀取少量的列。在面向列的數據庫中,您只能讀取所需的數據。例如,如果您需要100列中的5列,則I/O可能會減少20倍。
1.2 由于數據是以數據包的形式讀取的,因此壓縮比較容易。列中的數據也更容易壓縮。這進一步減少了I/O量。
1.3 由于減少的I/O,更多的數據適合在系統緩存中。
例如,查詢“統計每個廣告平臺的記錄數量”需要讀取一個“廣告平臺ID”列,其占用1個未壓縮字節。如果大多數流量不是來自廣告平臺,那么您可以期望至少有10倍的壓縮比。當使用快速壓縮算法時,數據解壓縮速度可以達到每秒至少幾千兆字節的未壓縮數據。換句話說,這個查詢可以在一臺服務器上以每秒大約幾十億行的速度處理。這個速度實際上是在實踐中是容易實現的。
milovidov@████████.yandex.ru:~$ clickhouse-client
ClickHouse client version 0.0.52053.
Connecting to localhost:9000.
Connected to ClickHouse server version 0.0.52053.
:) SELECT CounterID, count() FROM hits GROUP BY CounterID ORDER BY count() DESC LIMIT 20
SELECT
CounterID,
count()
FROM hits
GROUP BY CounterID
ORDER BY count() DESC
LIMIT 20
┌─CounterID─┬──count()─┐
│? ? 114208 │ 56057344 │
│? ? 115080 │ 51619590 │
│? ? ? 3228 │ 44658301 │
│? ? 38230 │ 42045932 │
│? ? 145263 │ 42042158 │
│? ? 91244 │ 38297270 │
│? ? 154139 │ 26647572 │
│? ? 150748 │ 24112755 │
│? ? 242232 │ 21302571 │
│? ? 338158 │ 13507087 │
│? ? 62180 │ 12229491 │
│? ? 82264 │ 12187441 │
│? ? 232261 │ 12148031 │
│? ? 146272 │ 11438516 │
│? ? 168777 │ 11403636 │
│? 4120072 │ 11227824 │
│? 10938808 │ 10519739 │
│? ? 74088 │? 9047015 │
│? ? 115079 │? 8837972 │
│? ? 337234 │? 8205961 │
└───────────┴──────────┘
20 rows in set. Elapsed: 0.153 sec. Processed 1.00 billion rows, 4.00 GB (6.53 billion rows/s., 26.10 GB/s.)
:)
2.對于CPU
由于執行查詢需要處理大量的行,因此它有助于為整個向量而不是單獨的行指派所有操作,或者實現查詢引擎,以便沒有指派成本。如果你不這樣做,任何半象限的磁盤子系統,查詢解釋器不可避免地中斷CPU。將數據存儲在列中并在可能的情況下按列處理是有意義的。
有兩種方法可以做到這一點:
1.向量引擎。所有的操作都是為向量而寫的,而不是單獨的值。這意味著您不需要經常調用操作,調度成本可以忽略不計。操作代碼包含一個優化的內部循環。
2.代碼生成。為查詢生成的代碼具有所有的間接調用。
這不是在“普通”數據庫中完成的,因為運行簡單查詢時沒有意義。但是,也有例外。例如,MemSQL在處理SQL查詢時使用代碼生成來減少延遲。(為了比較,分析DBMS需要優化吞吐量,而不是延遲。)
請注意,為了提高CPU效率,查詢語言必須是聲明式的(SQL或MDX),或者至少是一個向量(J,K)。查詢應該只包含隱式循環,以便優化。
ClickHouse的顯著特性
1.真正的面向列的DBMS
2.數據高效壓縮
3.磁盤存儲的數據
4.多核并行處理
5.在多個服務器上分布式處理
6. SQL語法支持
7.向量化引擎
8.實時數據更新
9.索引
10.適合在線查詢
11.支持近似預估計算
12.支持嵌套的數據結構
支持數組作為數據類型
13.支持限制查詢復雜性以及配額
14.復制數據復制和對數據完整性的支持
我們來看看其中的一些功能:
1.真正的面向列的DBMS
在一個真正的面向列的DBMS中,沒有任何“垃圾”存儲在值中。例如,必須支持定長數值,以避免在數值旁邊存儲長度“數字”。例如,十億個UInt8類型的值實際上應該消耗大約1 GB的未壓縮磁盤空間,否則這將強烈影響CPU的使用。由于解壓縮的速度(CPU使用率)主要取決于未壓縮的數據量,所以即使在未壓縮的情況下,緊湊地存儲數據(沒有任何“垃圾”)也是非常重要的。
因為有些系統可以單獨存儲單獨列的值,但由于其他場景的優化,無法有效處理分析查詢。例如HBase,BigTable,Cassandra和HyperTable。在這些系統中,每秒鐘可以獲得大約十萬行的吞吐量,但是每秒不會達到數億行。
另外,ClickHouse是一個DBMS,而不是一個單一的數據庫。ClickHouse允許在運行時創建表和數據庫,加載數據和運行查詢,而無需重新配置和重新啟動服務器。
2.數據壓縮
一些面向列的DBMS(InfiniDB CE和MonetDB)不使用數據壓縮。但是,數據壓縮確實提高了性能。
3.磁盤存儲的數據
許多面向列的DBMS(SAP HANA和Google PowerDrill)只能在內存中工作。但即使在數千臺服務器上,內存也太小,無法在Yandex.Metrica中存儲所有瀏覽量和會話。
4.多核并行處理
多核多節點并行化大型查詢。
5.在多個服務器上分布式處理
上面列出的列式DBMS幾乎都不支持分布式處理。在ClickHouse中,數據可以駐留在不同的分片上。每個分片可以是用于容錯的一組副本。查詢在所有分片上并行處理。這對用戶來說是透明的。
6. SQL支持
如果你熟悉標準的SQL,我們不能真正談論SQL的支持。
NULL不支持。
所有的函數都有不同的名字。
JOIN支持。
子查詢在FROM,IN,JOIN子句中被支持;
標量子查詢支持。
關聯子查詢不支持。
7.向量化引擎
數據不僅按列存儲,而且由矢量 - 列的部分進行處理。這使我們能夠實現高CPU性能。
8.實時數據更新
ClickHouse支持主鍵表。為了快速執行對主鍵范圍的查詢,數據使用合并樹(MergeTree)進行遞增排序。由于這個原因,數據可以不斷地添加到表中。添加數據時無鎖處理。
9.索引
例如,帶有主鍵可以在特定的時間范圍內為特定客戶端(Metrica計數器)抽取數據,并且延遲時間小于幾十毫秒。
10.支持在線查詢
這讓我們使用該系統作為Web界面的后端。低延遲意味著可以無延遲實時地處理查詢,而Yandex.Metrica界面頁面正在加載(在線模式)。
11.支持近似計算
1.系統包含用于近似計算各種值,中位數和分位數的集合函數。
2.支持基于部分(樣本)數據運行查詢并獲得近似結果。在這種情況下,從磁盤檢索比例較少的數據。
3.支持為有限數量的隨機密鑰(而不是所有密鑰)運行聚合。在數據中密鑰分發的特定條件下,這提供了相對準確的結果,同時使用較少的資源。
12.數據復制和對數據完整性的支持。
使用異步多主復制。寫入任何可用的副本后,數據將分發到所有剩余的副本。系統在不同的副本上保持相同的數據。數據在失敗后自動恢復,或對復雜情況使用“按鈕”。有關更多信息,請參閱“數據復制”一節。
ClickHouse目前未實現功能
1.無事務處理。
2.對于聚合,查詢結果必須適合單個服務器上的內存。但是,查詢的源數據量可能無限大。
3.缺乏全面的UPDATE / DELETE實現
Yandex.Metrica任務
我們需要根據點擊和會話獲取自定義報告,并使用用戶設置的自定義。報告數據實時更新。查詢必須立即運行(在線模式)。我們必須能夠在任何時間段建立報告。必須計算復雜的匯總,例如唯一訪客的數量。目前(2014年4月),Yandex.Metrica每天接收約120億次事件(瀏覽量和鼠標點擊)。所有這些事件都必須存儲以建立自定義報告。單個查詢可能需要幾秒鐘掃描數億行,或者數百萬行不超過幾百毫秒。
匯總和非匯總數據
有一種流行的觀點認為,為了有效地計算統計數據,您必須匯總數據,因為這會減少數據量。
但是數據聚合是一個非常有限的解決方案,原因如下:
- 您必須具有用戶需要的預定義報告列表。用戶不能進行自定義報告。
- 聚合大量密鑰時,數據量不會減少,聚合無用。
- 對于大量的報告,聚合變化太多(組合爆炸)。
- 聚合高基數密鑰(如URL)時,數據量不會減少太多(小于兩倍)。出于這個原因,聚合的數據量可能會增長,而不是縮小。
- 用戶不會查看我們為他們計算的所有報告。大部分的計算是無用的。
- 各種聚合可能違反數據的邏輯完整性。
如果我們不匯總任何內容并使用非匯總的數據,這實際上可能會減少計算量。
但是,通過匯總,相當一部分工作脫離了線索,相對冷靜地完成了工作。相反,在線計算需要盡可能快地計算,因為用戶正在等待結果。
Yandex.Metrica有一個專門的系統來匯總稱為Metrage的數據,這個數據用于大多數報告。從2009年開始,Yandex.Metrica還使用專門的OLAP數據庫來處理非聚合數據,稱為OLAPServer,以前用于報告生成器。OLAPServer對非匯總數據運行良好,但是它有許多限制,不能根據需要用于所有報告。這些包括缺乏對數據類型(僅數字)的支持,以及無法實時增量更新數據(只能通過每天重寫數據來完成)。OLAPServer不是一個DBMS,而是一個專門的DB。
為了消除OLAPServer的限制,并解決所有報告使用非匯總數據的問題,我們開發了ClickHouse DBMS。
用于Yandex.Metrica和其他Yandex服務
ClickHouse在Yandex.Metrica中用于多種用途。其主要任務是使用非聚合數據以在線模式構建報告。它使用374個服務器的集群,在數據庫中存儲超過8萬億行(超過四十億個值)。壓縮數據量不計復制和復制,大約是800TB。未壓縮的數據量(以TSV格式)將大約為7PB。
ClickHouse還用于:
- 存儲WebVisor數據。
- 處理中間數據。
- 使用Google Analytics構建全球報告。
- 運行查詢以調試Metrica引擎。
- 分析來自API和用戶界面的日志。
ClickHouse在其他Yandex服務中至少安裝了十幾個安裝:搜索行業,市場,Direct,業務分析,移動開發,AdFox,個人服務等。
類似開源系統
有沒有類似的ClickHouse可用。目前(2016年5月),沒有任何可用的開源和免費系統具有上面列出的所有功能。但是,這些功能對于Yandex.Metrica是絕對必要的。
可能愚蠢的問題
1.為什么不使用map-reduce等系統?
像map-reduce這樣的系統是分布式計算系統,其中使用分布式排序來執行縮減階段。回顧這個方面,map-reduce與YAMR,Hadoop,YT等其他系統類似。
這些系統由于延遲而不適合在線查詢,所以不能用于后臺級別的網頁界面。這樣的系統也不適合實時更新。分布式排序并不是減少操作的最佳解決方案,如果操作的結果和所有中間結果都存在,就像通常在聯機分析查詢的情況下發生的那樣,它們適合單個服務器的運行內存。在這種情況下,執行reduce操作的最佳方法是使用散列表。map-reduce任務的常用優化方法是在內存中使用散列表的組合操作(partial reduce)。這個優化是由用戶手動完成的。分布式排序是簡單的map-reduce作業長時間延遲的主要原因。
與map-reduce類似的系統可以在集群上運行任何代碼。但是,對于OLAP,使用情況下的執行查詢語言更為合適,因為經過調研它們可以更快地運行。例如,Hadoop有Hive和Pig。還有其他:Cloudera Impala,Shark (depricated)andSpark SQLforSpark,Presto,Apache Drill.。然而,與專門系統的性能相比,這些任務的性能是非常不理想的,相對較高的延遲不允許將這些系統用作網絡接口的后端。YT允許您存儲單獨的一組列。但YT不是一個真正的列式存儲系統,因為系統沒有固定長度的數據類型(所以你可以有效地存儲一個數字而不是“垃圾”),而且沒有向量化引擎。YT中的任務由流模式下的任意代碼執行,因此不能被充分優化(每臺服務器每秒高達數億行)。在2014-2016年,YT將開發使用合并樹,強類型值和類SQL語言支持的“動態表格排序”功能。動態排序的表不適用于OLAP任務,因為數據存儲在行中。YT中的查詢語言開發仍處于孵化階段,不能專注于這個功能。YT開發人員正在考慮在OLTP和Key-Value方案中使用動態排序的表。
性能
根據內部測試結果,ClickHouse在可用于測試的同類系統中顯示出最佳性能。這包括長查詢的最高吞吐量和短查詢的最低延遲。測試結果顯示在此頁面上。
吞吐量為單個大型查詢
吞吐量可以以每秒行數或兆字節每秒來衡量。如果數據放置在頁面緩存中,則在現代硬件上處理不太復雜的查詢,在單個服務器上以大約2-10 GB / s的未壓縮數據的速度進行處理(對于最簡單的情況,速度可能會達到30 GB / s)。如果數據不在頁面緩存中,則速度取決于磁盤子系統和數據壓縮率。例如,如果磁盤子系統允許以400 MB / s讀取數據,并且數據壓縮率為3,則速度將在1.2 GB / s左右。要獲得每秒行數的速度,請將查詢中使用的列的總大小除以每秒字節數。例如,如果提取10個字節的列,速度將在每秒大約1到2億行。
處理速度對于分布式處理幾乎線性地增加,但是只有在聚合或排序產生的行數不太大的情況下。
處理短的查詢時延遲
如果一個查詢使用一個主鍵,并且沒有選擇太多的行來處理(成千上萬),并且不使用太多的列,我們可以預計到不到50毫秒的延遲(最好的情況下,單位為毫秒)if數據被放置在頁面緩存中。否則,延遲是根據搜索的數量來計算的。如果使用旋轉驅動器,對于沒有過載的系統,延遲時間通過以下公式計算:查找時間(10 ms)*查詢的列數*數據部分的數量。
處理大量的短查詢時的吞吐量
在相同的條件下,ClickHouse可以在單個服務器上每秒處理幾百個查詢(在最好的情況下可以達到幾千個)。由于這種情況對分析型DBMS并不常見,因此我們建議每秒最多可以查詢100個查詢。
數據插入性能
我們建議將數據插入至少1000行的數據包中,或者每秒不超過一個請求。從制表符分隔轉儲插入到MergeTree表時,插入速度將從50到200 MB / s。如果插入的行大小約為1Kb,速度將從每秒50,000到200,000行。如果行很小,則每秒的行數會更高(Yandex Banner System數據 - > 500,000行/秒,Graphite數據 - > 1,000,000行/秒)。為了提高性能,可以并行執行多個INSERT查詢,并且性能會線性增加。