本文匯總了雲資料庫ClickHouse的常見問題及解決方案。
選型與購買
擴容與縮容
串連
遷移與同步
資料寫入與查詢
資料存放區
監控、升級、系統參數
其他
雲資料庫ClickHouse和官方版本對比多了哪些功能和特性?
雲資料庫ClickHouse主要對社區版本進行穩定性Bug修複,同時提供資源隊列進行使用者角色層級的資源使用優先順序配置。
購買雲資料庫ClickHouse執行個體時,推薦選擇哪一個版本?
雲資料庫ClickHouse根據開源社區公開的LTS核心穩定版提供服務,通常在版本推出3個月相對穩定後啟動雲端服務售賣。當前建議購買21.8及以上版本。更多版本功能對比,請參見版本功能對比。
單雙副本執行個體各有什麼特點?
單副本執行個體每一個Shard節點無副本節點,無高可用服務保障。資料安全性雲端式盤多副本儲存,性價比高。
雙副本執行個體每一個Shard節點對應一個副本服務節點,在主節點故障不能提供服務時副本節點可提供容災服務支援。
購買鏈路資源時顯示“目前範圍資源不足”,應該如何處理?
解決方案:您可以選擇同地區的其他地區購買。VPC網路支援相同地區不同可用性區域之間打通,同地區網路延遲無感知。
水平擴縮容耗時受什麼影響?
水平擴縮容過程涉及資料搬遷,執行個體裡面資料越多搬得越多,耗時時間越長。
擴縮容期間對執行個體有什麼影響?
為保證擴縮容中資料搬遷後的資料一致性,擴縮容期間執行個體處於可讀不可寫狀態。
水平擴縮容升級有什麼建議?
水平擴縮容耗時較長,當叢集效能不滿足時,請優先選擇垂直升配。如何進行垂直升配,請參見社區相容版叢集垂直變更配置和水平擴縮容。
每個連接埠的含義是什嗎?
協議 | 連接埠號碼 | 適用情境 |
TCP | 3306 | 使用clickhouse-client工具串連雲資料庫ClickHouse時配置,詳細操作請參見通過命令列工具串連ClickHouse。 |
HTTP | 8123 | 使用JDBC方式串連雲資料庫ClickHouse時配置進行應用開發,詳細操作請參見通過JDBC方式串連ClickHouse。 |
HTTPS | 8443 | 使用HTTPS協議訪問雲資料庫ClickHouse時配置,詳細操作請參見通過HTTPS協議串連ClickHouse。 |
每種開發語言通過SDK串連雲資料庫ClickHouse對應的連接埠是什嗎?
開發語言 | HTTP協議 | TCP協議 |
Java | 8123 | 3306 |
Python | ||
Go |
Go、Python語言對應推薦什麼SDK?
詳情請參見第三方開發庫。
如何處理用戶端工具串連叢集時報錯:connect timed out?
為什麼MySQL、HDFS、Kafka等外表無法連通?
目前20.3和20.8版本在建立相關外表時程式內會自動進行驗證,如果建立表成功,那說明網路是通的。如果無法建立成功,常見原因如下。
目標端和ClickHouse不在同一個VPC內,網路無法連通。
MySQL端存在白名單相關設定,需要在MySQL端添加ClickHouse的白名單。
對於Kafka外表,表建立成功,但查詢沒有結果。常見原因是Kafka中資料通過表結構給出的欄位和格式解析失敗,報錯資訊會給出解析失敗的具體位置。
為什麼程式無法串連ClickHouse?
常見原因及解決方案如下。
常見原因1:VPC網路、公網網路環境不對。同一VPC內可用內網串連,不在同一VPC內需開設公網後串連。
解決方案:開通公網詳情請參見申請和釋放外網地址。
常見原因2:白名單未配置。
解決方案:設定白名單詳情請參見設定白名單。
常見原因3:ECS安全性群組未放開。
解決方案:開放安全性群組詳情請參見安全性群組操作指引。
常見原因4:公司設定了網路防火牆。
解決方案:修改防火牆規則。
常見原因5:串連串中的帳號密碼包含特殊字元
!@#$%^&*()_+=,這些特殊字元在串連時無法被識別,導致執行個體串連失敗。解決辦法:您需要在串連串中對特殊字元進行轉義處理,轉義規則如下。
! : %21 @ : %40 # : %23 $ : %24 % : %25 ^ : %5e & : %26 * : %2a ( : %28 ) : %29 _ : %5f + : %2b = : %3d樣本:密碼為
ab@#c時,在串連串中對特殊字元進行轉義處理,密碼對應為ab%40%23c。常見原因6:雲資料庫ClickHouse會預設為您掛載CLB。CLB為隨用隨付,如果您的帳號欠費可能會導致您的雲資料庫ClickHouse無法訪問。
解決辦法:查詢阿里雲帳號是否欠費。如果欠費請及時進行繳費。
如何處理ClickHouse逾時問題?
雲資料庫ClickHouse核心中有很多逾時相關的參數設定,並且提供了多種協議進行互動,例如您可以設定HTTP協議和TCP協議的相關參數處理雲資料庫ClickHouse逾時問題。
HTTP協議
HTTP協議是雲資料庫ClickHouse在生產環境中最常使用的互動方式,包括官方提供的jdbc driver、阿里雲DMS、DataGrip,後台使用的都是HTTP協議。HTTP協議常用的連接埠號碼為8123。
如何處理distributed_ddl_task_timeout逾時問題
分布式DDL查詢(帶有 on cluster)的執行等待時間,系統預設是180s。您可以在DMS上執行以下命令來設定全域參數,設定後需要重啟叢集。
set global on cluster default distributed_ddl_task_timeout = 1800;由於分布式DDL是基於ZooKeeper構建任務隊列非同步執行,執行等待逾時並不代表查詢失敗,只表示之前發送還在排隊等待執行,使用者不需要重複發送任務。
如何處理max_execution_time逾時問題
一般查詢的執行逾時時間,DMS平台上預設設定是7200s,jdbc driver、DataGrip上預設是30s。逾時限制觸發之後查詢會自動取消。使用者可以進行查詢層級更改,例如
select * from system.numbers settings max_execution_time = 3600,也可以在DMS上執行以下命令來設定全域參數。set global on cluster default max_execution_time = 3600;
如何處理socket_timeout逾時問題
HTTP協議在監聽socket返回結果時的等待時間,DMS平台上預設設定是7200s,jdbc driver、DataGrip上預設是30s。該參數不是Clickhouse系統內的參數,它屬於jdbc在HTTP協議上的參數,但它是會影響到前面的max_execution_time參數設定效果,因為它決定了用戶端在等待結果返回上的時間限制。所以一般使用者在調整max_execution_time參數的時候也需要配套調整socket_timeout參數,略微高於max_execution_time即可。使用者佈建參數時需要在jdbc連結串上添加socket_timeout這個property,單位是毫秒,例如:'jdbc:clickhouse://127.0.0.1:8123/default?socket_timeout=3600000'。
使用ClickHouse服務端IP直接連結時的Client異常hang住
阿里雲上的ECS在跨安全性群組連結時,有可能陷入靜默連結錯誤。具體原因是jdbc用戶端所在ECS機器的安全性群組白名單並沒有開放給ClickHouse服務端機器。當用戶端的請求經過超長時間才得到查詢結果時,返回的報文可能因為路由表不通無法發送到用戶端。此時用戶端就陷入了異常hang住狀態。
該問題的處理辦法和SLB連結異常斷鏈問題一樣,開啟send_progress_in_http_headers可以解決大部分問題。在極少數情況下,開啟send_progress_in_http_headers仍不能解決問題的,您可以嘗試配置jdbc用戶端所在ECS機器的安全性群組白名單,把ClickHouse服務端地址加入到白名單中。
TCP協議
TCP協議最常使用的情境是ClickHouse內建的命令列工具進行互動分析時,社區相容版叢集常見連接埠號碼為3306。因為TCP協議裡有連結定時探活報文,所以它不會出現socket層面的逾時問題。您只需關注distributed_ddl_task_timeout和max_execution_time參數的逾時,設定方法和HTTP協議一致。
為什麼OSS外表匯入ORC、PARQUET等格式的資料,出現記憶體報錯或OOM掛掉?
常見原因:記憶體使用量率比較高。
您可以採取如下解決方案。
把OSS上的檔案拆分為一個一個的小檔案,然後再進行匯入。
進行記憶體的升配。如何升配,請參見社區相容版叢集垂直變更配置和水平擴縮容。
如何處理匯入資料報錯:too many parts?
ClickHouse每次寫入都會產生一個data part,如果每次寫入一條或者少量的資料,那會造成ClickHouse內部有大量的data part(會給merge和查詢造成很大的負擔)。為了防止出現大量的data part,ClickHouse內部做了很多限制,這就是too many parts報錯的內在原因。出現該錯誤,請增加寫入的批量大小。如果無法調整批量大小,可以在控制台修改參數:merge_tree.parts_to_throw_insert,將參數的取值設定的大一些。
為什麼DataX匯入速度慢?
常見原因及解決方案如下。
常見原因1:參數設定不合理。ClickHouse適合使用大batch、少數幾個並發進行寫入。多數情況下batch可以高達幾萬甚至幾十萬(取決於您的單行RowSize大小,一般按照每行100Byte進行評估,您需要根據實際資料特徵進行估算)。
解決方案:並發數建議不超過10個。您可以調整不同參數進行嘗試。
常見原因2:DataWorks獨享資源群組的ECS規格太小。比如獨享資源的CPU、Memory太小,導致並發數、網路出口頻寬受限;或者是batch設定太大而Memory太小,引起DataWorks進程Java GC等。
解決方案:您可以通過DataWorks的輸出日誌對ECS規格大小進行確認。
常見原因3:從資料來源中讀取慢。
解決方案:您可以在DataWorks輸出日誌中搜尋totalWaitReaderTime、totalWaitWriterTime,如果發現totalWaitReaderTime明顯大於totalWaitWriterTime,則表明主要耗時在讀取端,而不是寫入端。
常見原因4:使用了公網Endpoint。公網Endpoint的頻寬非常有限,無法承載高效能的資料匯入匯出。
解決方案:您需要替換為VPC網路的Endpoint。
常見原因5:有髒資料。在沒有髒資料的情況下,資料以batch方式寫入。但是遇到了髒資料,正在寫入的batch就會失敗,並回退到逐行寫入,產生大量的data part,大幅度降低了寫入速度。
您可以參考如下兩種方式判斷是否有髒資料。
查看報錯資訊,如果返回資訊包含
Cannot parse,則存在髒資料。代碼如下。
SELECT written_rows, written_bytes, query_duration_ms, event_time, exception FROM system.query_log WHERE event_time BETWEEN '2021-11-22 22:00:00' AND '2021-11-22 23:00:00' AND lowerUTF8(query) LIKE '%insert into <table_name>%' and type != 'QueryStart' and exception_code != 0 ORDER BY event_time DESC LIMIT 30;查看batch行數,如果batch行數變為1,則存在髒資料。
代碼如下。
SELECT written_rows, written_bytes, query_duration_ms, event_time FROM system.query_log WHERE event_time BETWEEN '2021-11-22 22:00:00' AND '2021-11-22 23:00:00' AND lowerUTF8(query) LIKE '%insert into <table_name>%' and type != 'QueryStart' ORDER BY event_time DESC LIMIT 30;
解決方案:您需要在資料來源刪除或修改髒資料。
為什麼Hive匯入後其資料行數跟ClickHouse對不上?
您可以通過以下手段進行排查。
首先通過系統資料表query_log來查看匯入的過程中是否有報錯,如果有報錯,那很有可能出現資料丟失的情況。
確定使用的表引擎是否可以去重,比如使用ReplacingMergeTree,那很可能出現ClickHouse中的Count小於Hive中的情況。
重新確認Hive中資料行數的正確性,很有可能出現源頭的行數確定錯誤的情況。
為什麼Kafka匯入後其資料行數跟ClickHouse對不上?
您可以通過以下手段進行排查。
首先通過系統資料表query_log來查看匯入的過程中是否有報錯,如果有報錯,那很有可能出現資料丟失的情況。
確定使用的表引擎是否可以去重,比如使用ReplacingMergeTree,那很可能出現ClickHouse中的Count小於Kafka中的情況。
查看Kafka外表的配置是否有kafka_skip_broken_messages參數的配置,如果有該參數,那可能會跳過解析失敗的Kafka訊息,導致ClickHouse總的行數是小於Kafka中的。
如何使用Spark、Flink匯入資料?
如何使用Spark匯入資料請參見從Spark匯入。
如何使用Flink匯入資料請參見從Flink SQL匯入。
如何從現有ClickHouse匯入資料到雲資料庫ClickHouse?
您可以採取如下方案。
通過ClickHouse Client以匯出檔案的形式進行資料移轉,詳情請參見將自建ClickHouse資料移轉至雲ClickHouse社區相容版。
通過Remote函數進行資料的遷移。
INSERT INTO <目的表> SELECT * FROM remote('<串連串>', '<庫>', '<表>', '<username>', '<password>');
使用MaterializeMySQL引擎同步MySQL資料時,為什麼出現如下報錯:The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION = 1, but the master has purged binary logs containing GTIDs that the slave requires?
常見原因:MaterializeMySQL引擎停止同步的時間太久,導致MySQL Binlog日誌到期被清理掉。
解決方案:刪除報錯的資料庫,重新在雲資料庫ClickHouse中建立同步的資料庫。
使用MaterializeMySQL引擎同步MySQL資料時,為什麼出現錶停止同步?為什麼系統資料表system.materialize_mysql中sync_failed_tables欄位不為空白?
常見原因:同步過程中使用了雲資料庫ClickHouse不支援的MySQL DDL語句。
解決方案:重新同步MySQL資料,具體步驟如下。
刪除停止同步的表。
DROP TABLE <table_name> ON cluster default;說明table_name為停止同步的表名。如果停止同步的表有分布式表,那麼本地表和分布式表都需要刪除。重啟同步進程。
ALTER database <database_name> ON cluster default MODIFY SETTING skip_unsupported_tables = 1;說明<database_name>為雲資料庫ClickHouse中同步的資料庫。
如何處理報錯:“Too many partitions for single INSERT block (more than 100)”?
常見原因:單個INSERT操作中超過了max_partitions_per_insert_block(最大分區插入塊,預設值為100)。ClickHouse每次寫入都會產生一個data part(資料部分),一個分區可能包含一個或多個data part,如果單個INSERT操作中插入了太多分區的資料,那會造成ClickHouse內部有大量的data part(會給合并和查詢造成很大的負擔)。為了防止出現大量的data part,ClickHouse內部做了限制。
解決方案:請執行以下操作,調整分區數或者max_partitions_per_insert_block參數。
調整表結構,調整分區方式,或避免單次插入的不同分區數超過限制。
避免單次插入的不同分區數超過限制,可根據資料量適當修改max_partitions_per_insert_block參數,放大單個插入的不同分區數限制,修改文法如下:
單節點執行個體
SET GLOBAL max_partitions_per_insert_block = XXX;多節點執行個體
SET GLOBAL ON cluster DEFAULT max_partitions_per_insert_block = XXX;說明ClickHouse社區推薦預設值為100,分區數不要設定得過大,否則可能對效能產生影響。在大量匯入資料後可修改值為預設值。
如何處理insert into select XXX記憶體超限報錯?
常見原因及解決方案如下。
常見原因1:記憶體使用量率比較高。
解決方案:調整參數max_insert_threads,減少可能的記憶體使用量量。
常見原因2:當前是通過
insert into select把資料從一個ClickHouse叢集匯入到另外一個叢集。解決方案:通過匯入檔案的方式來遷移資料,更多資訊請參見將自建ClickHouse資料移轉至雲ClickHouse社區相容版。
如何查詢CPU使用量和記憶體使用量量?
您可以在system.query_log系統資料表裡自助查看CPU和MEM在查詢時的使用日誌,裡面有每個查詢的CPU使用量和記憶體使用量量統計。更多資訊請參見system.query_log。
如何處理查詢時記憶體超出限制?
ClickHouse服務端對所有查詢線程都配有memory tracker,同一個查詢下的所有線程tracker會彙報給一個memory tracker for query,再上層還是memory tracker for total。您可以根據情況採取如下解決方案。
遇到
Memory limit (for query)超限報錯說明是查詢記憶體佔用過多(執行個體總記憶體的70%)導致失敗,這種情況下您需要垂直升配提高執行個體記憶體規模。遇到
Memory limit (for total)超限報錯說明是執行個體總記憶體使用量超限(執行個體總記憶體的90%),這種情況下您可以嘗試降低查詢並發,如果仍然不行則可能是後台非同步任務佔用了比較大的記憶體(常常是寫入後主鍵合并任務),您需要垂直升配提高執行個體記憶體規模。
為什麼企業版執行SQL的時候報錯memory limit?
原因分析:雲資料庫 ClickHouse 企業版叢集的計算單元CCU(ClickHouse Compute Units)個數為多節點的CCU總個數,單節點的規格是32c128g,即32CCU,記憶體上限為128g(含作業系統,實際可用記憶體量約為115g)。單條SQL預設在單節點上執行,因此,當單條SQL記憶體消耗超過115g時可能會報錯memory limit。
叢集的節點個數僅與叢集的CCU上限相關。當CCU上限大於64時,企業版叢集的節點數計算公式為:CCU上限/32;當CCU上限小於64時,企業版叢集的節點數為2。
解決方案:可以在SQL後面設定以下參數,讓SQL在多節點上並存執行,可能會降低負載,避免記憶體超出限制。
SETTINGS
allow_experimental_analyzer = 1,
allow_experimental_parallel_reading_from_replicas = 1;當執行Group By操作且結果集較大時,導致記憶體消耗過大SQL報錯如何解決?
可以設定 max_bytes_before_external_group_by 參數限制GROUP BY操作的記憶體消耗,需要注意,allow_experimental_analyzer 會影響此參數的生效。
如何處理查詢報並發超限?
預設Server查詢最大並發數為100,您可以在控制台上進行修改。修改運行參數值具體操作步驟如下。
在叢集列表頁面,選擇社區版執行個體列表,單擊目的地組群ID。
單擊左側導覽列的參數配置。
在參數配置頁面,單擊max_concurrent_queries參數的運行參數值後面的編輯按鈕。
在懸浮框中填寫目標值,單擊確定。

單擊提交參數。
單擊確定。
在資料停止寫入時,同一個查詢語句每次查詢的結果不一致,應該如何處理?
問題詳細描述:通過select count(*) 查詢資料時只有整體資料的大概一半,或者資料一直在跳變。
為什麼有時看不到已經建立好的表並且查詢結果一直抖動時多時少?
常見原因及解決方案如下。
常見原因1:建表流程存在問題。ClickHouse的分布式叢集搭建並沒有原生的分布式DDL語義。如果您在自建ClickHouse叢集時使用
create table建立表,查詢雖然返回了成功,但實際這個表只在當前串連的Server上建立了。下次串連重設換一個Server,您就看不到這個表了。解決方案:
建表時,請使用
create table <table_name> on cluster default語句,on cluster default聲明會把這條語句廣播給default叢集的所有節點進行執行。範例程式碼如下。CREATE TABLE test ON cluster default (a UInt64) Engine = MergeTree() ORDER BY tuple();在test表上再建立一個分布式表引擎,建表語句如下。
CREATE TABLE test_dis ON cluster default AS test Engine = Distributed(default, default, test, cityHash64(a));
常見原因2:ReplicatedMergeTree儲存表配置有問題。ReplicatedMergeTree表引擎是對應MergeTree表引擎的主備同步增強版,在單副本執行個體上限定只能建立MergeTree表引擎,在雙副本執行個體上只能建立ReplicatedMergeTree表引擎。
解決方案:在雙副本執行個體上建表時,請使用
ReplicatedMergeTree('/clickhouse/tables/{database}/{table}/{shard}', '{replica}')或ReplicatedMergeTree()配置ReplicatedMergeTree表引擎。其中,ReplicatedMergeTree('/clickhouse/tables/{database}/{table}/{shard}', '{replica}')為固定配置,無需修改。
如何處理往表裡寫入時間戳記資料後查詢出來的結果與實際資料不同?
用SELECT timezone()語句,查看時區是否為當地時區,如果不是修改timezone配置項的值為當地時區。如何修改請參見修改配置項運行參數值。
如何處理建表後查詢表不存在?
常見原因:DDL語句只在一個節點上執行。
解決方案:檢查DDL語句是否有on cluster關鍵字。更多資訊,請參見建表文法。
為什麼Kafka外表建表後資料不增加?
您可以先對Kafka外表進行select * from的查詢,如果查詢報錯,那可以根據報錯資訊確定原因(一般是資料解析失敗)。如果查詢正常返回結果,那需要進一步查看目的表(Kafka外表的具體儲存表)和Kafka源表(Kafka外表)的欄位是否匹配。如果資料寫入失敗,那說明欄位是匹配不上的。樣本語句如下。
insert into <目的表> as select * from <kafka外表>;為什麼用戶端看到的時間結果和時區顯示的不一樣?
用戶端設定了use_client_time_zone,並設定在了錯誤時區上。
資料寫入後不可見?
問題描述:為什麼資料寫入後,卻查詢不到資料?
原因:一般原因可能包括以下幾個方面。
分布式表和本地表的表結構不一致造成的。
寫入分布式表後,分布式臨時檔案未分發完成。
寫入雙副本其中一個副本後,副本同步未完成。
原因分析以及解決方案:
分布式表和本地表的表結構不一致
您可以通過查詢系統資料表system.distribution_queue來查看寫入分布式表的時候是否發生錯誤。
寫入分布式表後,分布式臨時檔案未分發完成
原因分析:在雲資料庫ClickHouse多節點形態下,如果業務通過網域名稱串連資料庫,並且INSERT語句是針對分布式表進行的,那麼這個INSERT請求通過前置的CLB組件轉寄後會隨機落在叢集中的某個節點上。在節點接收該INSERT請求之後,會先將一部分資料直接寫入本節點磁碟中進行儲存,另一部分資料作為臨時檔案暫存於本節點中,並後續非同步分發給叢集中的其他節點。當這個分發行為未完成時,下一次查詢可能無法查詢到未分發出去的資料。
解決方案:如果業務對於INSERT之後,立即查詢其結果的準確性有強需求的話,可以考慮在INSERT語句中增加settings insert_distributed_sync = 1,配置該參數之後,針對分布式表的INSERT會變為同步等待模式,所有的節點都完成分發後,INSERT才會返回成功。如何配置該參數,請參見下述內容:
設定此參數後,因為要同步等待資料分發,insert語句的執行時間可能會增加,業務上需要結合寫入效能考慮是否設定該參數。
設定此參數叢集維度生效,需謹慎考慮。建議您通過在單條query中添加該參數進行測試,確保驗證無誤後,再結合業務需求決定是否將其應用於叢集維度。
僅需單個query生效,則直接加在query後面,樣本如下。
INSERT INTO <table_name> values() settings insert_distributed_sync = 1;需叢集維度生效,則設定在user.xml中,如何設定,請參見配置user.xml參數。
寫入雙副本其中一個副本後,副本同步未完成
原因分析:在雲資料庫ClickHouse雙副本形態下,在執行INSERT語句時,兩個副本中只有隨機一個會實際執行該INSERT語句,而另一個副本將會非同步同步相關資料。因此在執行一條INSERT語句之後,當資料還未同步到另一個副本時,如果SELECT語句請求被未同步資料完成的副本執行時,則會出現查詢不到預期資料的現象。
解決方案:如果業務對於INSERT之後,對其立即查詢的結果準確性有強需求的話,可以考慮在寫入語句中增加settings insert_quorum = 2,配置該參數之後,副本間資料同步會變為同步等待模式,所有的副本同步結束之後,INSERT才會返回成功。
設定此參數,需注意以下事項:
設定此參數後,需要等待副本之間的資料同步完成,INSERT語句的執行時間可能會增加,業務上需要結合寫入效能考慮是否設定該參數。
設定此參數後,因為INSERT要等待副本之間同步完成才能執行成功,這意味著如果有副本不可用,則配置了insert_quorum = 2的所有寫入均會失敗,這與雙副本的可靠性保證是衝突的。
設定此參數叢集維度生效,需謹慎考慮。建議您通過在單條query中添加該參數進行測試,確保驗證無誤後,再結合業務需求決定是否將其應用於叢集維度。
僅需單個query生效,則直接加在query後面,樣本如下。
INSERT INTO <table_name> values() settings insert_quorum = 2;需叢集維度生效,則設定在user.xml中,如何設定,請參見配置user.xml參數。
為什麼ClickHouse設定TTL後,資料到期未刪除?
問題描述
業務表已經正確配置了TTL,但是表中的到期資料未自動刪除,TTL不生效。
排查方法
檢查表的TTL設定是否合理。
根據業務實際情況設定TTL,建議到天層級,避免秒、分鐘層級的TTL設定(例如
TTL event_time + INTERVAL 30 SECOND)。檢查參數
materialize_ttl_after_modify。該參數用於控制在執行
ALTER MODIFY TTL語句後,是否對存量資料應用新的TTL規則。預設設定為1表示開啟;0表示僅對新資料生效,存量資料不會受到TTL限制。查看參數設定
SELECT * FROM system.settings WHERE name like 'materialize_ttl_after_modify';修改參數設定
重要此命令會掃描所有存量資料,資源壓力會比較大,請謹慎使用。
ALTER TABLE $table_name MATERIALIZE TTL;
診斷分區清理策略。
ttl_only_drop_parts參數值為1時,表示只有當資料分區(part)內所有資料都到期時才整體刪除該分區。查看
ttl_only_drop_parts參數設定SELECT * FROM system.merge_tree_settings WHERE name LIKE 'ttl_only_drop';查看分區到期情況
SELECT partition, name, active, bytes_on_disk, modification_time, min_time, max_time, delete_ttl_info_min, delete_ttl_info_max FROM system.parts c WHERE database = 'your_dbname' AND TABLE = 'your_tablename' LIMIT 100;delete_ttl_info_min:表示該part中用於TTL DELETE規則的最小日期時間索引值。
delete_ttl_info_max:表示該part中用於TTL DELETE規則的最大日期時間索引值。
如果分區規則與TTL規則不匹配,可能導致部分資料遲遲無法被整體清理。分區規則與TTL規則匹配說明如下。
partition規則與TTL規則一致(例如分區規則是按天分區,TTL規則也是按天刪除),則可以通過partition_id判定TTL,一次TTL一個分區,這種策略的代價最低。推薦結合分區(如按天分區)和
ttl_only_drop_parts=1設定,高效刪除到期資料,提升效能。partition規則與TTL規則一致不匹配,且
ttl_only_drop_parts = 1,則通過每個part的ttl_info進行匹配。只有當整個part都超過了delete_ttl_info_max時間,才會做TTL。partition規則與TTL規則一致不匹配,且
ttl_only_drop_parts = 0,則需要掃描每個part的資料,找出需要刪除資料進行刪除,這種策略代價最大。
控制合并觸發頻率。
到期資料的刪除是在資料合併(merge)過程中非同步完成,而不是即時立即刪除。可以通過
merge_with_ttl_timeout參數控制合并頻率,或通過ALTER TABLE ... MATERIALIZE TTL強制觸發TTL應用。查看參數
SELECT * FROM system.merge_tree_settings WHERE name = 'merge_with_ttl_timeout';說明單位為秒,線上預設值為7200秒(2小時)。
修改參數
如果
merge_with_ttl_timeout設定過高,TTL合并觸發頻率會降低,導致到期資料長時間未被清理。可以適當調低該參數以加快清理頻率,具體操作請參見參數說明。
檢查線程池參數設定。
資料的TTL淘汰是在part的合并階段執行,TTL受參數
max_number_of_merges_with_ttl_in_pool(線上執行個體預設值為2)和background_pool_size(線上執行個體預設值為16)限制。查詢當前後台線程活動情況
SELECT * FROM system.metrics WHERE metric LIKE 'Background%';其中“BackgroundPoolTask ”表示對“background_pool_size”指標的即時監控值。
修改參數
當您的其他參數設定沒有異常時,且在CPU較為空白閑的情況下,結合業務情況,首先可以適當調大
max_number_of_merges_with_ttl_in_pool參數,例如從2調整到4 ,或者從4調整到8;如果調整之後還是沒有效果,建議您調大background_pool_size參數。重要調整
max_number_of_merges_with_ttl_in_pool參數需要重啟叢集,調大background_pool_size參數無需重啟叢集,但調小background_pool_size參數需要重啟叢集。
檢查表結構或分區設計是否合理。
如果表沒有合理分區,或者分區粒度過大,TTL清理效率會降低。為高效清理到期資料,建議分區粒度與 TTL 粒度一致(如都按天),具體操作請參見最佳實務。
檢查叢集磁碟空間是否充足。
TTL是伴隨merge操作在後台觸發的,需要預留一定的磁碟空間,當有大part存在或者空間不足(水位超過90%)時,可能也會導致無法TTL。
檢查
system.merge_tree_settings中的其他系統參數設定。merge_with_recompression_ttl_timeout:使用重新壓縮 TTL 重複合并之前的最小延遲,線上執行個體預設設定為4小時。預設情況下,TTL規則將至少每 4 小時應用於業務表一次。如果您需要更頻繁地應用 TTL 規則,只需修改上述設定即可。max_number_of_merges_with_ttl_in_pool:控制TTL任務數的可以使用的最大線程數的參數,當後台線程池中進行中的帶有TTL的合并任務數量超過該參數指定的值時,不再分配新的帶有 TTL 的合并任務。
為什麼optimize任務很慢?
optimize任務非常佔用CPU和磁碟輸送量,查詢和optimize任務都會相互影響,在機器節點負載壓力較大的時候就會表現出optimize很慢問題,目前沒有特殊最佳化方法。
為什麼optimize後資料仍未主鍵合并?
首先為了讓資料有正確的主鍵合并邏輯,需要保證以下兩個前提條件。
儲存表裡的partition by定義欄位必須是包含在
order by裡的,不同分區的資料不會主鍵合并。分布式表裡定義的Hash演算法欄位必須是包含在
order by裡的,不同節點的資料不會主鍵合并。
optimize常用命令及相關說明如下。
命令 | 說明 |
| 嘗試選取MergeTree的data parts進行合并,有可能沒有執行任務就返回。執行了也並不保證全表的記錄都完成了主鍵合并,一般不會使用。 |
| 指定某個分區,選取分區中所有的data parts進行合并,有可能沒有執行任務就返回。任務執行後代表某個分區下的資料都合并到了同一個data part,單分區下已經完成主鍵合并。但是在任務執行期間寫入的資料不會參與合并,若是分區下只有一個data part也不會重複執行任務。 說明 對於沒有分區鍵的表,其預設分區就是partition tuple()。 |
| 對全表所有分區強制進行合并,即使分區下只有一個data part也會進行重新合并,可以用於強制移除TTL到期的記錄。任務執行代價最高,但也有可能沒有執行合并任務就返回。 |
對於上面三種命令,您可以設定參數optimize_throw_if_noop通過異常報錯感知是否執行任務。
為什麼optimize後資料TTL仍未生效?
常見原因及解決方案如下。
常見原因1:資料的TTL淘汰是在主鍵合并階段執行的,如果data part遲遲沒有進行主鍵合并,那到期的資料就無法淘汰。
解決方案:
您可以通過手動
optimize final或者optimize 指定分區的方式觸發合并任務。您可以在建表時設定merge_with_ttl_timeout、ttl_only_drop_parts等參數,提高含有到期資料data parts的合并頻率。
常見原因2:表的TTL經過修改或者添加,存量的data part裡缺少TTL資訊或者不正確,這樣也可能導致到期資料淘汰不掉。
解決方案:
您可以通過
alter table materialize ttl命令重建TTL資訊。您可以通過
optimize 分區更新TTL資訊。
為什麼optimize後更新刪除操作沒有生效?
雲資料庫ClickHouse中的更新刪除都是非同步執行的,目前沒有機制可以幹預其進度。您可以通過system.mutations系統資料表查看進度。
如何進行DDL增加列、刪除列、修改列操作?
本地表的修改直接執行即可。如果要對分布式表進行修改,需分如下情況進行。
如果沒有資料寫入,您可以先修改本地表,然後修改分布式表。
如果資料正在寫入,您需要區分不同的類型進行操作。
類型
操作步驟
增加Nullable的列
修改本地表。
修改分布式表。
修改列的資料類型(類型可以相互轉換)
刪除Nullable列
修改分布式表。
修改本地表。
增加非Nullable的列
停止資料的寫入。
執行SYSTEM FLUSH DISTRIBUTED分布式表。
修改本地表。
修改分布式表。
重新進行資料的寫入。
刪除非Nullable的列
修改列的名稱
為什麼DDL執行慢,經常卡住?
常見原因:DDL全域的執行是串列執行,複雜查詢會導致死結。
您可以採取如下解決方案。
等待運行結束。
在控制台嘗試終止查詢。
如何處理分布式DDL報錯:longer than distributed_ddl_task_timeout (=xxx) seconds?
您可以通過使用set global on cluster default distributed_ddl_task_timeout=xxx命令修改預設逾時時間,xxx為自訂逾時時間,單位為秒。全域參數修改請參見叢集參數修改。
如何處理文法報錯:set global on cluster default?
常見原因及解決方案如下。
常見原因1:ClickHouse用戶端會進行文法解析,而
set global on cluster default是服務端增加的文法。在用戶端尚未更新到與服務端對齊的版本時,該文法會被用戶端攔截。解決方案:
使用JDBC Driver等不會在用戶端解析文法的工具,比如DataGrip、DBeaver。
編寫JDBC程式來執行該語句。
常見原因2:
set global on cluster default key = value;中value是字串,但是漏寫了引號。解決方案:在字串類型的value兩側加上引號。
有什麼BI工具推薦?
Quick BI。
有什麼資料查詢IDE工具推薦?
DataGrip、DBEaver。
雲資料庫ClickHouse支援向量檢索嗎?
雲資料庫ClickHouse支援向量檢索。更多詳情,參見以下文檔:
在建表時報ON CLUSTER is not allowed for Replicated database怎麼辦?
如果您的叢集是企業版叢集,且建表語句中包含ON CLUSTER default,可能會報錯ON CLUSTER is not allowed for Replicated database,建議您將執行個體版本升級至最新版本,部分小版本存在此缺陷。如何升級版本,請參見升級核心小版本。
分布式表使用子查詢(JOIN或IN聯表查詢)時報Double-distributed IN/JOIN subqueries is denied (distributed_product_mode = 'deny')怎麼辦?
問題描述:如果您的叢集是多節點的社區版叢集,查詢中使用多個分布式表JOIN或IN聯表查詢時,可能會報錯Exception: Double-distributed IN/JOIN subqueries is denied (distributed_product_mode = 'deny'). 。
原因分析:當多個分布式表JOIN或IN聯表查詢時,會導致查詢放大。例如,以3個節點為例,分布式表JOIN或IN聯表的查詢規模將擴大為3*3個本地表的子查詢,這將導致資源浪費和延遲增加,故系統預設不允許此類查詢執行。
解決原理:將IN或JOIN替換為GLOBAL IN或GLOBAL JOIN,讓GLOBAL IN或GLOBAL JOIN右側子查詢在一個節點完成後儲存到暫存資料表,將暫存資料表發送給其他節點用於上一級查詢。
將IN或JOIN替換為GLOBAL IN或GLOBAL JOIN的影響:
暫存資料表將被發送到所有遠程伺服器,盡量避免使用大型資料集。
使用remote函數查詢外部執行個體的資料,將IN或JOIN替換為GLOBAL IN或GLOBAL JOIN後,原本應該在外部執行個體執行的子查詢會在本執行個體執行,可能導致查詢結果錯誤。
例如,在執行個體a執行以下語句,使用remote函數查詢外部執行個體
cc-bp1wc089c****的資料。SELECT * FROM remote('cc-bp1wc089c****.clickhouse.ads.aliyuncs.com:3306', `default`, test_tbl_distributed1, '<your_Account>', '<YOUR_PASSWORD>') WHERE id GLOBAL IN (SELECT id FROM test_tbl_distributed1);根據上述解決原理理解該語句,執行個體a將執行GLOBAL IN右側的子查詢
SELECT id FROM test_tbl_distributed1產生暫存資料表A,並將暫存資料表的資料傳給執行個體cc-bp1wc089c****用於上一級查詢。最終,執行個體cc-bp1wc089c****執行的語句是SELECT * FROM default.test_tbl_distributed1 WHERE id IN (暫存資料表A);以上為GLOBAL IN或GLOBAL JOIN的執行原理。延續上述例子,進一步理解,為什麼將IN或JOIN替換為GLOBAL IN或GLOBAL JOIN後,使用remote函數查詢外部執行個體的資料,可能導致結果錯誤。
根據上述描述,執行個體
cc-bp1wc089c****最終執行的語句是SELECT * FROM default.test_tbl_distributed1 WHERE id IN (暫存資料表A);,但這裡的條件集暫存資料表A卻是在執行個體a執行得到的,上述樣本,原本最終執行個體cc-bp1wc089c****執行的應該是SELECT * FROM default.test_tbl_distributed1 WHERE id IN (SELECT id FROM test_tbl_distributed1 );條件集應該來源於執行個體cc-bp1wc089c****,所以由於使用GLOBAL IN或GLOBAL JOIN後,導致子查詢得到條件集的來源錯誤,導致結果錯誤。
解決方案:
方案一:修改業務代碼中的SQL,手工將IN或JOIN改成GLOBAL IN或GLOBAL JOIN。
例如您可以將以下語句:
SELECT * FROM test_tbl_distributed WHERE id IN (SELECT id FROM test_tbl_distributed1);添加GLOBAL,修改為
SELECT * FROM test_tbl_distributed WHERE id GLOBAL IN (SELECT id FROM test_tbl_distributed1);方案二:修改系統參數distributed_product_mode或者prefer_global_in_and_join,系統自動將IN或JOIN替換為GLOBAL IN或GLOBAL JOIN。
distributed_product_mode
使用以下語句,設定distributed_product_mode為global,使系統自動將IN或JOIN查詢替換為GLOBAL IN或者GLOBAL JOIN。
SET GLOBAL ON cluster default distributed_product_mode='global';distributed_product_mode使用說明
作用:ClickHouse中的一個重要設定,用於控制分布式子查詢的行為。
值描述:
deny(預設值):禁止使用IN和JOIN子查詢,會拋出
"Double-distributed IN/JOIN subqueries is denied"異常。local:將子查詢中的資料庫和表替換為目標伺服器(分區)的本地表,保留普通的IN或JOIN。
global:將IN或JOIN查詢替換為GLOBAL IN或者GLOBAL JOIN。
allow:允許使用IN和JOIN子查詢。
適用情境:僅適用於查詢中使用多個分布式表JOIN或IN聯表查詢。
prefer_global_in_and_join
prefer_global_in_and_join
使用以下語句,設定prefer_global_in_and_join為1,使系統自動將IN或JOIN查詢替換為GLOBAL IN或者GLOBAL JOIN。
SET GLOBAL ON cluster default prefer_global_in_and_join = 1;prefer_global_in_and_join使用說明
作用:ClickHouse 中的一個重要設定,用於控制 IN 和 JOIN 操作符的行為。
值描述:
0(預設值):禁止使用IN和JOIN子查詢,會拋出
"Double-distributed IN/JOIN subqueries is denied"異常。1:啟用IN和JOIN子查詢,將IN或JOIN查詢替換為GLOBAL IN或者GLOBAL JOIN。
適用情境:僅適用於查詢中使用多個分布式表JOIN或IN聯表查詢。
如何查看每張表所佔的磁碟空間?
您可以通過如下代碼查看每張表所佔的磁碟空間。
SELECT table, formatReadableSize(sum(bytes)) as size, min(min_date) as min_date, max(max_date) as max_date FROM system.parts WHERE active GROUP BY table; 如何查看冷資料大小?
範例程式碼如下。
SELECT * FROM system.disks;如何查詢哪些資料在冷存上?
範例程式碼如下。
SELECT * FROM system.parts WHERE disk_name = 'cold_disk';如何移動分區資料到冷存?
範例程式碼如下。
ALTER TABLE table_name MOVE PARTITION partition_expr TO DISK 'cold_disk';為什麼監控中存在資料中斷情況?
常見原因如下。
查詢觸發OOM。
修改配置觸發重啟。
升降配後的執行個體重啟。
20.8後的版本是否支援平滑升級,不需要遷移資料?
ClickHouse的叢集是否支援平滑升級,主要取決於叢集的建立時間。對於2021年12月01日之後購買的叢集,支援原地平滑升級核心大版本,無需遷移資料。而對於2021年12月01日之前購買的叢集,則需要通過資料移轉的方式進行核心大版本升級。如何升級版本,請參見升級核心大版本。
常用系統資料表有哪些?
常用系統資料表及作用如下。
名稱 | 作用 |
system.processes | 查詢正在執行的SQL。 |
system.query_log | 查詢歷史執行過的SQL。 |
system.merges | 查詢叢集上的merge資訊。 |
system.mutations | 查詢叢集上的mutation資訊。 |
如何修改系統層級的參數?是否要重啟,有什麼影響?
系統層級的參數對應config.xml內的部分配置項,具體修改步驟如下。
在叢集列表頁面,選擇社區版執行個體列表,單擊目的地組群ID。
單擊左側導覽列的參數配置。
在參數配置頁面,單擊max_concurrent_queries參數的運行參數值後面的編輯按鈕。
在懸浮框中填寫目標值,單擊確定。

單擊提交參數。
單擊確定。
單擊確定後,自動重啟clickhouse-server,重啟會造成約1min閃斷。
如何修改使用者層級的參數?
使用者層級的參數對應users.xml內的部分配置項,你需要執行如下樣本語句。
SET global ON cluster default ${key}=${value};無特殊說明的參數執行成功後即可生效。
如何修改Quota?
您可以在執行語句的settings裡增加,範例程式碼如下。
settings max_memory_usage = XXX;為什麼節點之間的CPU使用率、記憶體使用量率、記憶體使用量量差別很大?
如果您的叢集是雙副本,或單副本多節點的叢集,在進行較多寫入操作時,寫入節點的CPU和記憶體使用量率將高於其他節點。待資料同步至其他節點後,CPU和記憶體使用量率將趨於基本平衡。
如何查看系統的詳細日誌資訊?
問題描述:
如何查看系統的詳細日誌資訊,以便排查錯誤或發現潛在問題。
解決方案:
查看叢集text_log.level參數,進行以下操作:
text_log.level為空白,表示您未開啟text_log,您需設定text_log.level以開啟text_log。
text_log.level不為空白,查看text_log等級是否滿足目前需求,如不滿足,您需修改此參數,設定text_log等級。
如何查看和修改text_log.level參數,請參見配置config.xml參數。
登入目標資料庫。如何登入,請參見串連資料庫。
執行以下語句,查看分析。
SELECT * FROM system.text_log;
如何解決目的地組群與資料來源網路互連問題?
如果目的地組群與資料來源使用相同的VPC並位於同一地區。您需檢查二者是否將IP地址添加到了對方的白名單中。如果沒有,請添加白名單。
ClickHouse中如何添加白名單,請參見設定白名單。
其他資料來源如何添加白名單,請參見自身產品文檔。
如果目的地組群與資料來源不屬於上述情況,選擇合適的網路解決方案,解決網路問題後再將彼此IP地址添加到對方的白名單中。
情境 | 解決方案 |
雲上雲下互連 | |
跨地區跨帳號VPC互連 | |
同地區不同VPC互連 | |
跨地區跨帳號VPC互連 | |
使用公網互連 |
ClickHouse社區版叢集支援遷移至企業版叢集嗎?
ClickHouse社區版叢集支援遷移至企業版叢集。
企業版叢集與社區版叢集相互遷移資料的主要方式有兩種,通過remote函數和通過檔案匯出匯入方式。具體操作,請參見將自建ClickHouse資料移轉至雲ClickHouse社區相容版。
資料移轉時不同分區的庫表結構不一致,如何處理?
問題描述
資料移轉要求所有分區的庫表結構一致,否則會導致部分庫表結構無法遷移。
解決方案
MergeTree表(非物化視圖inner表)的庫表結構在不同分區不一致。
建議排查商務邏輯是否導致分區間表結構存在差異:
若業務預期所有分區表結構應完全一致,請自行重新建立。
若業務預期不同分區的表結構不同,請提交工單聯絡支援人員進行處理。
物化視圖inner表在不同分區不一致。
方案1:重新命名inner表,並將物化視圖、分布式表顯示指定到目標MergeTree表。以原物化視圖
up_down_votes_per_day_mv為例,操作步驟如下。列出數量不等於節點數的表。NODE_NUM=分區數*副本數。
SELECT database,table,any(create_table_query) AS sql,count() AS cnt FROM cluster(default, system.tables) WHERE database NOT IN ('system', 'information_schema', 'INFORMATION_SCHEMA') GROUP BY database, table HAVING cnt != <NODE_NUM>;查看inner表數量不正常的物化視圖。
SELECT substring(hostName(),38,8) AS host,* FROM cluster(default, system.tables) WHERE uuid IN (<UUID1>, <UUID2>, ...);關閉預設的叢集同步行為(雲資料庫ClickHouse必須關閉,自建ClickHouse無需執行),並重新命名inner表,使得各節點的表名一致(為降低操作風險,以下操作請擷取各個節點IP,串連連接埠3005,逐個節點執行)。
SELECT count() FROM mv_test.up_down_votes_per_day_mv; SET enforce_on_cluster_default_for_ddl=0; RENAME TABLE `mv_test`.`.inner_id.9b40675b-3d72-4631-a26d-25459250****` TO `mv_test`.`up_down_votes_per_day`;刪除物化視圖(逐個節點執行)。
SELECT count() FROM mv_test.up_down_votes_per_day_mv; SET enforce_on_cluster_default_for_ddl=0; DROP TABLE mv_test.up_down_votes_per_day_mv;建立物化視圖顯示指向重新命名的inner表(逐個節點執行)。
SELECT count() FROM mv_test.up_down_votes_per_day_mv; SET enforce_on_cluster_default_for_ddl=0; CREATE MATERIALIZED VIEW mv_test.up_down_votes_per_day_mv TO `mv_test`.`up_down_votes_per_day` ( `Day` Date, `UpVotes` UInt32, `DownVotes` UInt32 ) AS SELECT toStartOfDay(CreationDate) AS Day, countIf(VoteTypeId = 2) AS UpVotes, countIf(VoteTypeId = 3) AS DownVotes FROM mv_test.votes GROUP BY Day;注意:物化視圖必須按照原定義格式定義目標表的列,不能使用SELECT推測,否則可能出現異常。例如,列
tcp_cn在SELECT時使用sumIf,在目標表中應定義為sum。正確用法
CREATE MATERIALIZED VIEW net_obs.public_flow_2tuple_1m_local TO net_obs.public_flow_2tuple_1m_local_inner ( ... tcp_cnt AggregateFunction(sum, Float64), ) AS SELECT ... sumIfState(pkt_cnt, protocol = '6') AS tcp_cnt, FROM net_obs.public_flow_5tuple_1m_local ...錯誤用法
CREATE MATERIALIZED VIEW net_obs.public_flow_2tuple_1m_local TO net_obs.public_flow_2tuple_1m_local_inner AS SELECT ... sumIfState(pkt_cnt, protocol = '6') AS tcp_cnt, FROM net_obs.public_flow_5tuple_1m_local ...
方案2:重新命名inner表,物化視圖全域重建,遷移inner表資料。
方案3:雙寫物化視圖,等7天。
相同的SQL,在原有執行個體中未報錯,但在企業版的24.5或更新的版本執行個體中,卻發生錯誤,應該如何處理?
建立的企業版24.5及以後的版本執行個體,其查詢引擎預設使用新analyzer。新analyzer具有更好的查詢效能,但可能與部分舊版SQL不相容,從而導致解析錯誤。如遇該錯誤,您可執行以下語句,將新analyzer回退至舊analyzer。更多新analyzer詳情,請參見進一步瞭解全新analyzer。
SET allow_experimental_analyzer = 0;如何暫停雲資料庫ClickHouse叢集?
ClickHouse社區版叢集暫不支援暫停功能,企業版叢集支援此功能。如果您需要暫停企業版叢集,您可前往企業版叢集列表,在叢集列表頁面左上方,選中目標地區,在叢集列表找到目的地組群,單擊目的地組群操作列的
>暫停。
如何將叢集中的MergeTree錶轉為ReplicatedMergeTree表?
問題描述
由於使用者不熟悉ClickHouse的特性原理,在使用多複本集群時,經常會誤建立一些MergeTree引擎的表,這樣就會導致各個分區的副本節點之間的資料不會相互同步,進而導致在查詢分布式表時,每次查詢的資料會不一致。這時就需要將原來的MergeTree引擎表,轉化為ReplicatedMergeTree引擎表。
解決方案
在ClickHouse中,沒有對應的DDL語句直接修改表的儲存引擎,所以要把MergeTree錶轉為ReplicatedMergeTree表,只能建立ReplicatedMergeTree表,並將MergeTree的資料匯入至ReplicatedMergeTree的方式進行。
例如您的多複本集群中有一個引擎為MergeTree類型的表table_src,其對應的分布式表為table_src_d。轉換為ReplicatedMergeTree引擎表,請參見以下步驟:
建立ReplicatedMergeTree類型的目標表table_dst,對應的分布式表為table_dst_d。如何建表,請參見CREATE TABLE。
將引擎為MergeTree類型的表table_src中的資料匯入至table_dst_d。有如下兩種方案:
以下兩種方案在查詢來源資料時,都是對MergeTree的本地表的查詢。
往目標表中插入時,資料量不是特別多的情況下,為了使資料均衡 ,直接插入到分布式表table_dst_d中。
如果原來的MergeTree表table_src的資料在各個節點均衡,且資料量特別大,可以直接插入到ReplicatedMergeTree引擎的本地表table_dst中。
如果資料量大,執行時間會很長,使用remote函數時,需注意remote函數的逾時時間的設定。
使用remote函數匯入資料
擷取各個節點IP。
SELECT cluster, shard_num, replica_num, is_local, host_address FROM system.clusters WHERE cluster = 'default';使用remote函數,匯入資料。
將上個步驟擷取的各節點的IP,依次傳入remote函數中,並執行。
INSERT INTO table_dst_d SELECT * FROM remote('node1', db.table_src) ;例如,查詢到兩個節點IP分別為10.10.0.165、10.10.0.167,然後分別執行如下的insert語句:
INSERT INTO table_dst_d SELECT * FROM remote('10.10.0.167', default.table_src) ; INSERT INTO table_dst_d SELECT * FROM remote('10.10.0.165', default.table_src) ;所有節點IP帶入執行完成後,即可完成將叢集中的MergeTree錶轉為ReplicatedMergeTree表。
使用本地表匯入資料
如果您在下有的VPC下有ECS,且安裝了ClickHouse的client端,也可以通過client分別登入到各個節點執行以下操作。
擷取各個節點IP。
SELECT cluster, shard_num, replica_num, is_local, host_address FROM system.clusters WHERE cluster = 'default';匯入資料。
使用節點IP依次登入各個節點,執行以下語句。
INSERT INTO table_dst_d SELECT * FROM db.table_src ;所有節點依次登入執行後,即可完成將叢集中的MergeTree錶轉為ReplicatedMergeTree表。
如何使多個SQL語句在同一個Session中執行?
通過設定唯一的session_id標識符,ClickHouse服務端會為同一Session ID的請求維護相同的上下文環境,實現多個SQL語句在同一個Session中執行。以使用ClickHouse Java Client (V2)串連ClickHouse為例,實現關鍵步驟如下:
在Maven專案的pom.xml中添加依賴。
<dependency> <groupId>com.clickhouse</groupId> <artifactId>client-v2</artifactId> <version>0.8.2</version> </dependency>在CommandSetting中增加自訂的
Session ID。package org.example; import com.clickhouse.client.api.Client; import com.clickhouse.client.api.command.CommandSettings; public class Main { public static void main(String[] args) { Client client = new Client.Builder() // 添加執行個體存取點 .addEndpoint("endpoint") // 添加使用者名稱 .setUsername("username") // 添加密碼 .setPassword("password") .build(); try { client.ping(10); CommandSettings commandSettings = new CommandSettings(); // 設定session_id commandSettings.serverSetting("session_id","examplesessionid"); // 在session內設定參數max_block_size = 65409 client.execute("SET max_block_size=65409 ",commandSettings); // 執行查詢 client.execute("SELECT 1 ",commandSettings); client.execute("SELECT 2 ",commandSettings); } catch (Exception e) { throw new RuntimeException(e); } finally { client.close(); } } }
上述樣本中的2條SELECT語句均在同一個Session內,並且他們的max_block_size參數均為65409。更多ClickHouse Java Client使用詳情,請參見Java Client | ClickHouse Docs。
為何ClickHouse的FINAL關鍵詞去重因JOIN失效?
問題描述
使用 FINAL 關鍵字對查詢去重時,若 SQL 中包含 JOIN,去重失效,結果仍存在重複資料。樣本SQL如下:
SELECT * FROM t1 FINAL JOIN t2 FINAL WHERE xxx;問題原因
此問題是ClickHouse官方未修複的已知bug,因 FINAL 和 JOIN 執行邏輯衝突導致去重失效。更多詳情,請參見ClickHouse's issues。
解決方案
方案一(推薦):啟用實驗性最佳化器,在查詢末尾添加配置,啟用query級
FINAL(無需表級聲明)。樣本如下:例如原SQL為:
SELECT * FROM t1 FINAL JOIN t2 FINAL WHERE xxx;您需去除表名後的
FINAL關鍵字,在SQL末尾增加settings allow_experimental_analyzer = 1,FINAL = 1,語句調整結果如下:SELECT * FROM t1 JOIN t2 WHERE xxx SETTINGS allow_experimental_analyzer = 1, FINAL = 1;重要僅23.8及以上版本支援
allow_experimental_analyzer參數。如您的版本小於23.8,建議您升級版本後調整SQL語句。如何升級,請參見升級核心大版本。方案二(謹慎使用):
強制合并去重:定期執行
OPTIMIZE TABLE 本地表名 FINAL提前合并資料(大表慎用,IO 開銷高)。查詢SQL調整:移除
FINAL關鍵字,資料去重依賴合并後資料查詢。
重要謹慎操作,表資料量較大時會消耗較大IO,影響效能。
為何ClickHouse社區相容版刪除/更新資料操作一直未完成?
問題描述
ClickHouse社區相容版叢集,執行資料刪除(DELETE)或更新(UPDATE)操作時,任務長時間處於未完成狀態。
原因分析
與MySQL的同步操作不同,ClickHouse社區相容版叢集的DELETE和UPDATE操作基於Mutation機制非同步執行,非即時生效。Mutation的核心流程如下:
提交任務:使用者執行
ALTER TABLE ... UPDATE/DELETE產生非同步任務。標記資料:後台建立
mutation_*.txt記錄待修改的資料範圍(不立即生效)。後台重寫:ClickHouse逐步重寫受影響的
data part,合并時應用變更。清理舊資料:舊資料區塊在合并完成後被標記刪除。
分析上述Mutation流程,如果短時間內下發過多Mutation操作,可能導致Mutation任務阻塞,進而導致刪除和更新資料操作一直未完成。建議您在下發Mutation之前,通過下述SQL,查看當前是否有大量Mutation在運行,如果沒有,再進行下發Mutation,避免造成Mutation堆積。
SELECT * FROM clusterAllReplicas('default', system.mutations) WHERE is_done = 0;解決方案
檢查叢集是否存在過多正在執行的Mutation。
您可通過下述SQL,查看叢集當前Mutation情況。
SELECT * FROM clusterAllReplicas('default', system.mutations) WHERE is_done = 0;如果存在較多正在執行的Mutation,您需使用高許可權帳號取消部分或全部Mutation任務。
取消單表上所有Mutation任務。
KILL MUTATION WHERE database = 'default' AND table = '<table_name>'取消某個Mutation任務。
KILL MUTATION WHERE database = 'default' AND table = '<table_name>' AND mutation_id = '<mutatiton_id>'其中,mutatiton_id可通過以下SQL擷取。
SELECT mutation_id, * FROM clusterAllReplicas('default', system.mutations) WHERE is_done = 0;
為何ClickHouse社區相容版叢集連續查詢資料結果不一致?
問題描述
雲資料庫ClickHouse社區相容版,使用相同的SQL語句多次進行查詢時,查詢返回的結果存在不一致的情況。
原因分析
導致社區相容版叢集同一SQL多次查詢,返回結果不一致的主要原因有2個,具體原因及分析如下:
多分區叢集多次查詢的目標表是本地表。
社區相容版的多分區叢集在建表時,除了建立本地表,還需要建立分布式表。此類叢集,資料寫入流程大概如下:
當有資料寫入時,資料會先寫入到分布式表中,然後由分布式表將資料分發到不同分區上的本地表進行儲存。
查詢資料時,查詢的表類型不同,資料來源也會不同,具體如下:
查詢分布式表:分布式表會將各個分區上本地表的資料彙總起來一起返回。
查詢本地表:每次查詢只會返回隨機分區上本地表的資料,這種情況下,就會出現每次查詢結果與上一次不一致的現象。
雙複本集群在建立表時沒有使用
Replicated*系列引擎。社區相容版的雙複本集群在建表時需使用Replicated*系列引擎,例如ReplicatedMergeTree引擎。Replicated*系列引擎可實現副本之間的資料同步。
如果雙複本集群在建立表時沒有使用Replicated*系列引擎,副本之間資料沒有相互同步,則多次查詢也會出現結果不一致的現象。
解決方案
確定叢集類型。
您需根據叢集資訊判斷叢集是多分區叢集、雙複本集群還是多分區雙複本集群。具體操作如下:
在頁面左上方,選擇社區版執行個體列表。
在叢集列表中,單擊目的地組群ID,進入叢集資訊頁面。
查看叢集屬性的系列和配置資訊的節點群組個數。判斷叢集類型,具體邏輯如下:
節點群組個數大於1:多分區叢集。
系列等於高可用版:雙複本集群。
上述2個條件都滿足:多分區雙複本集群。
根據叢集類型,選擇處理方法。
多分區叢集
檢查查詢的表類型,如果是本地表,您需查詢分布式表。
如果沒有建立分布式表,您需建立分布式表。如何建立分布式表,請參見建立表。
雙複本集群
查看目標表的建表語句,其引擎是不是
Replicated*系列引擎,如果不是,需要重新建立表。如何建表,請參見建立表。多分區雙複本集群
檢查查詢的表類型。
如果是本地表,您需查詢分布式表。如果沒有建立分布式表,您需建立分布式表。
如果查詢的是分布式表,您需檢查分布式表對應的本地表的引擎是不是
Replicated*系列引擎,如果不是,您需重新建立本地表,其引擎使用Replicated*系列引擎。如何建表,請參見建立表。
為何ClickHouse社區相容版叢集使用optimize命令強制資料合併後,ReplacingMergeTree引擎仍未去重?
問題描述
ClickHouse的ReplacingMergeTree引擎表在資料合併過程中,會對主鍵相同的資料執行去重操作。使用以下命令進行強制資料合併後,仍可尋找到主鍵相同的重複資料。
optimize TABLE <table_name> FINAL ON cluster default;原因分析
ReplacingMergeTree引擎的去重僅作用於單節點。若主鍵相同的資料因分區運算式sharding_key未顯式指定(預設rand()隨機分配)而分散到不同節點,則無法保證整查詢整個叢集時資料不重複,因為ReplacingMergeTree引擎無法跨節點去重。
解決方案
重新建立本地表和分布式表,在建立分布式表時,將分區運算式sharding_key設定為本地表的主鍵。建表文法請參見CREATE TABLE。
分布式表和本地表都需要重新建立。如果只重建分布式表,也只能對新插入的資料起效,存量資料依然無法去重。