FAQ

Updated at:

This topic describes common ApsaraDB for ClickHouse issues and their solutions.

ApsaraDB for ClickHouse vs. community version

ApsaraDB for ClickHouse primarily fixes stability bugs in the community version. It also provides resource queues to set resource usage priorities by user role.

Recommended versions for ApsaraDB for ClickHouse

ApsaraDB for ClickHouse uses stable Long-Term Support (LTS) kernel versions from the open-source community. New versions are typically available on the cloud service after a three-month stabilization period. We recommend purchasing version 21.8 or later. For a detailed comparison, see Version Feature Comparison.

Single-replica vs. master-replica instances

  • A single-replica instance does not have a replica node for each shard node and therefore provides no high availability. Its data security relies on the multi-replica storage of the underlying cloud disk, making it a highly cost-effective option.

  • A master-replica instance provides a replica node for each shard node. If a primary node fails, the corresponding replica node provides disaster recovery.

Insufficient resources error

Try purchasing the resources in a different zone within the same region. A VPC network connects zones within the same region with negligible network latency.

Factors affecting horizontal scaling time

Because horizontal scaling involves data migration, the process takes longer for instances with more data.

Impact of scaling

To ensure data consistency after data migration, an instance enters a read-only state during the scaling process.

Horizontal scaling recommendations

Horizontal scaling takes a long time. If your cluster's performance is insufficient, prioritize vertical scaling. For instructions, see Vertical scaling and horizontal scaling for Community Edition clusters.

Port descriptions

Supported versions

Protocol

Port number

Description

Community Edition / Enterprise Edition

TCP

3306

Use this port to connect to ApsaraDB for ClickHouse using the clickhouse-client tool. For more information, see Connect to ClickHouse using a command line interface.

Community Edition / Enterprise Edition

HTTP

8123

Use this port to connect to ApsaraDB for ClickHouse using JDBC for application development. For more information, see Connect to ClickHouse using JDBC.

Community Edition

MySQL

9004

Use this port to connect to ApsaraDB for ClickHouse using the MySQL protocol. For more information, see Connect to ClickHouse using the MySQL protocol.

Community Edition / Enterprise Edition

HTTPS

8443

Use this port to access ApsaraDB for ClickHouse over HTTPS. For more information, see Connect to ClickHouse using the HTTPS protocol.

SDK connection ports for Alibaba Cloud ClickHouse

Language

HTTP

TCP

Java

8123

3306

Python

Go

SDKs for Go and Python

The recommended SDKs are listed in Third-Party Client Libraries.

Resolve the "connect timed out" error

Try the following solutions.

  • Check network connectivity. Use ping to check network reachability and telnet to verify that database ports 3306 and 8123 are open.

  • Verify your ClickHouse whitelist configuration. For instructions, see Configure a whitelist.

  • Confirm the public IP address of your client machine. On an office network, this address can change frequently, so use an IP lookup service to find the correct one. For an example, see whatsmyip.

Cannot connect to external tables

In versions 20.3 and 20.8, the system automatically validates the connection when you create an external table. Successful table creation confirms that the network connection is working. If table creation fails, common reasons include:

  • The target endpoint and ClickHouse are not in the same VPC, which prevents network connectivity.

  • The MySQL server uses a whitelist. You must add ClickHouse to the MySQL whitelist.

For Kafka external tables, if a table is created successfully but queries return no data, the cause is often that the data in Kafka fails to parse according to the table schema. The error message will indicate the exact location of the parsing failure.

Troubleshoot connection issues

This topic describes common causes of connection failures and their solutions.

  • Cause: The network environment is misconfigured. You can connect over an internal network only if your application and the instance are in the same VPC. If they are in different VPCs, you must enable a public endpoint and connect over the public network.

    Solution: To enable public network access, see Apply for and release public IP addresses.

  • Cause: The client's IP address is not in the instance whitelist.

    Solution: To configure the whitelist, see Configure a whitelist.

  • Cause: The security group for your ECS instance blocks traffic on the required port.

    Solution: To configure the security group, see Security group operation guide.

  • Cause: A corporate firewall is blocking the connection.

    Solution: Modify your firewall rules to allow outbound traffic to the instance.

  • Cause: The username or password in the connection string contains special characters, such as !@#$%^&*()_+=. The client might not interpret these characters correctly, which causes a connection failure.

    Solution: You must URL-encode any special characters in the connection string. The encoding rules are as follows:

    ! : %21
    @ : %40
    # : %23
    $ : %24
    % : %25
    ^ : %5e
    & : %26
    * : %2a
    ( : %28
    ) : %29
    _ : %5f
    + : %2b
    = : %3d

    For example, if your password is ab@#c, the encoded password in the connection string must be ab%40%23c.

  • Cause: ApsaraDB for ClickHouse automatically provisions a pay-as-you-go Server Load Balancer (SLB) instance for your cluster. If your Alibaba Cloud account has overdue payments, the SLB instance may be suspended, making your ApsaraDB for ClickHouse instance inaccessible.

    Solution: Check your Alibaba Cloud account for overdue payments. If you have an outstanding balance, pay the amount due to restore the service. For more information, see What is a financial account?

Handle ClickHouse timeout issues

ApsaraDB for ClickHouse provides various timeout-related parameters and supports multiple interaction protocols. For example, you can configure parameters for the HTTP and TCP protocols to manage timeouts.

HTTP protocol

The HTTP protocol is the most common method for interacting with ApsaraDB for ClickHouse in production environments. Clients such as the official JDBC driver, Alibaba Cloud DMS, and DataGrip all use the HTTP protocol in the background. The default port for the HTTP protocol is 8123.

  • How to handle distributed_ddl_task_timeout issues

    • This parameter specifies the wait time for distributed DDL queries (with an ON CLUSTER clause) to execute. The default value is 180 seconds. You can run the following command in Alibaba Cloud DMS to set this as a global parameter. The new setting takes effect after a cluster restart.

      set global on cluster default distributed_ddl_task_timeout = 1800;

      Because ZooKeeper manages and executes distributed DDL tasks asynchronously in a queue, a timeout indicates that the task is still queued for execution, not that it has failed. Do not resubmit the task.

  • How to handle max_execution_time timeout issues

    • This parameter specifies the maximum execution time for a query. The default value is 7200 seconds on the Alibaba Cloud DMS platform and 30 seconds for clients like the JDBC driver and DataGrip. When this time limit is reached, ClickHouse automatically cancels the query. You can override this setting at the query level. For example: select * from system.numbers settings max_execution_time = 3600. Alternatively, you can run the following command in Alibaba Cloud DMS to set it as a global parameter.

      set global on cluster default max_execution_time = 3600;
  • How to handle socket_timeout issues

    • This parameter specifies the wait time for a listening socket to return a result over the HTTP protocol. The default value is 7200s on the DMS platform, and 30s for the JDBC driver and DataGrip. This parameter is not a ClickHouse system parameter, but a JDBC parameter for the HTTP protocol. However, it affects the effectiveness of the max_execution_time parameter setting because it determines the client-side time limit for waiting for a result. Therefore, when you adjust the max_execution_time parameter, you must also adjust the socket_timeout parameter to a value slightly higher than max_execution_time. To set this parameter, add the socket_timeout property to the JDBC connection string. The value is specified in milliseconds. For example: 'jdbc:clickhouse://127.0.0.1:8123/default?socket_timeout=3600000'.

  • Client hangs when connecting directly to the ClickHouse server IP address

    • When an ECS instance connects to a ClickHouse server across security groups, a silent connection failure may occur. This failure can happen if the IP address of the ClickHouse server is not in the security group whitelist of the ECS instance that runs the JDBC client. If a long-running query is executed, routing issues may prevent the delivery of response packets to the client, which causes the client to hang.

      Similar to resolving transient connection issues with an SLB instance, enabling send_progress_in_http_headers can resolve most of these problems. In the rare cases where this setting does not work, add the IP address of the ClickHouse server to the security group whitelist of the ECS instance where the client is running.

TCP protocol

The TCP protocol is most commonly used for interactive analysis with the native command-line tool of ClickHouse. The common port for Community Edition clusters is 3306, and for Enterprise Edition clusters, it is 9000. Because the TCP protocol includes keep-alive packets, it does not experience socket-level timeouts. You only need to manage the distributed_ddl_task_timeout and max_execution_time parameters. You can set them using the same method as for the HTTP protocol.

Connection refused (localhost:9000) error

  • Problem: After you create a dictionary in ApsaraDB for ClickHouse, you receive the following error when you run a query: "Code: 210. DB::NetException: Connection refused (localhost:9000). (NETWORK_ERROR) (version 23.8.16.1)".

  • Cause: ApsaraDB for ClickHouse uses port mapping. The port displayed in the console (for example, 9000) is the load balancer port, not the port that the node actually listens on. When you access the instance using localhost, you must use the actual node port instead of the load balancer port.

  • Solution: Connect to the actual node port. For example, change localhost:9000 to localhost:3003. The following table lists the common port mappings for the Community-compatible Edition.

    Load balancer port

    Actual node port

    3306

    3003

    9000

    3003

    8123

    3002

    9004

    3005

    8443

    3006

ApsaraDB for ClickHouse: Cannot access Prometheus port

  • Problem: You have configured Prometheus parameters for an ApsaraDB for ClickHouse cluster, but you cannot access the specified Prometheus port. For example, the telnet cc-xxxx.clickhouse.ads.aliyuncs.com:port-number command fails to connect.

  • Cause: The endpoint provided in the console directs traffic to a load balancer, while the Prometheus service runs on the underlying ApsaraDB for ClickHouse nodes. The load balancer does not forward traffic on custom ports to these nodes.

  • Solution: Connect directly to the underlying nodes. Run the following command to find their IP addresses.

    SELECT * FROM system.clusters;

OOM errors during OSS data import

Common cause: High memory usage.

To resolve this issue, do one of the following:

How to resolve the "too many parts" error

ClickHouse generates a data part for each write operation. Writing a single row or small amounts of data at a time creates an excessive number of data parts, which heavily burdens merge operations and queries. The "too many parts" error occurs because ClickHouse enforces internal limits to prevent this. If this error occurs, increase your write batch size. If you cannot adjust the batch size, increase the value of the merge_tree.parts_to_throw_insert parameter in the console.

Why are DataX imports slow?

This topic describes common causes of slow DataX imports and their solutions.

  • Cause 1: Suboptimal parameter configuration. ClickHouse performs best with a large batch size and a small number of concurrent operations. A single batch can often contain tens or even hundreds of thousands of rows, depending on your average row size. As a general guideline, you can estimate based on 100 bytes per row, but you should adjust this value based on your actual data characteristics.

    Solution: Set the number of concurrent operations to 10 or fewer. Experiment with different parameter values to find the optimal configuration for your workload.

  • Cause 2: Insufficient resources in the DataWorks exclusive resource group. The ECS instances in the exclusive resource group may be undersized. Insufficient CPU or memory can limit the number of concurrent operations and the available network egress bandwidth. Likewise, setting a large batch size on a machine with limited memory can trigger frequent Java garbage collection (GC) in the DataWorks process, which slows down performance.

    Solution: Check the DataWorks output logs for the ECS instance specifications.

  • Cause 3: The bottleneck is at the data source.

    Solution: In the DataWorks output logs, search for the totalWaitReaderTime and totalWaitWriterTime metrics. If totalWaitReaderTime is significantly higher than totalWaitWriterTime, the bottleneck is on the read side (the data source), not the write side.

  • Cause 4: Use of a public network endpoint. A public network endpoint has limited bandwidth and is unsuitable for high-performance data import or export operations.

    Solution: Switch to a VPC network endpoint.

  • Cause 5: Presence of dirty data. Normally, data is written in a batch. However, if dirty data is encountered, the current batch write fails. DataX then falls back to a row-by-row insertion mode. This fallback generates excessive data parts and drastically reduces write performance.

    You can use the following two methods to check for dirty data.

    • Check for error messages. If the log contains a Cannot parse error, this indicates dirty data.

      You can use the following SQL query to find exceptions.

      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;
    • Monitor the batch row count. If the number of rows per batch drops to 1, this strongly indicates that DataX has encountered dirty data and switched to row-by-row mode.

      You can use the following SQL query to check the row count.

      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;

    Solution: Identify and correct or remove the dirty data from the data source.

Row count mismatch after Hive import

To troubleshoot this issue, perform the following checks.

  1. Check the query_log system table for errors during the import. If any errors exist, data loss has likely occurred.

  2. Check if your table engine supports deduplication. For example, if you use the ReplacingMergeTree table engine, the number of rows in ClickHouse may be lower than in Hive because this engine removes duplicates.

  3. Verify the accuracy of the number of rows in the Hive source, as the source's initial count may be inaccurate.

Row count mismatch between ClickHouse and Kafka

To troubleshoot this issue, check the following:

  1. Check the query_log system table for errors that occurred during the import. If errors are present, data loss may have occurred.

  2. Check if your table engine performs data deduplication. For example, the ReplacingMergeTree engine removes duplicate entries, which lowers the row count in ClickHouse compared to Kafka.

  3. Check if the kafka_skip_broken_messages parameter is enabled in your Kafka external table configuration. If enabled, ClickHouse skips messages that fail to parse, reducing the row count in ClickHouse compared to Kafka.

Data import with Spark and Flink

Import data from an existing ClickHouse

Use one of the following methods:

MaterializeMySQL sync error: 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

This error indicates that the MaterializeMySQL engine stopped synchronizing for an extended period, causing the MySQL binary log to expire and be purged.

To resolve this issue, delete the affected database and then recreate it in ApsaraDB for ClickHouse.

Why do tables stop synchronizing and why is the sync_failed_tables field in the system.materialize_mysql system table not empty when you use the MaterializeMySQL engine to synchronize MySQL data?

Common cause: You ran a MySQL Data Definition Language (DDL) statement that ApsaraDB for ClickHouse does not support during synchronization.

Solution: Follow these steps to resynchronize the MySQL data.

  1. Delete the table that stopped synchronizing.

    DROP TABLE <table_name> ON cluster default;
    Note

    In this command, table_name is the name of the table that stopped synchronizing. If the table is a distributed table, you must delete both the distributed table and its local table.

  2. Restart the synchronization process.

    ALTER database <database_name> ON cluster default MODIFY SETTING skip_unsupported_tables = 1;
    Note

    In this command, <database_name> is the name of the synchronized database in ApsaraDB for ClickHouse.

Resolving the error "Too many partitions for single INSERT block (more than 100)"

This error occurs when a single INSERT operation attempts to write to more partitions than allowed by the max_partitions_per_insert_block parameter, which defaults to 100. In ClickHouse, each write operation creates a data part. A partition can contain one or more data parts. If an INSERT statement writes data to too many distinct partitions at once, it generates too many data parts, which can strain merge and query operations. To prevent performance degradation, ClickHouse enforces this limit.

To resolve this issue, you can adjust your partitioning strategy or modify the max_partitions_per_insert_block parameter.

  • Adjust the table schema, modify the partitioning method, or ensure that a single insert operation does not exceed the partition limit.

  • If your use case requires writing to many partitions at once, you can increase the max_partitions_per_insert_block limit based on your data volume. Use the following syntax to modify the parameter:

    Single-node instance

    SET GLOBAL max_partitions_per_insert_block = XXX;

    Multi-node instance

    SET GLOBAL ON cluster DEFAULT max_partitions_per_insert_block = XXX;
    Note

    The ClickHouse community recommends the default value of 100. Setting this value too high can degrade performance. After your bulk data import is complete, you can revert the parameter to its default value.

Memory limit exceeded error for insert into select

Querying CPU and memory usage

The system.query_log system table provides statistics on CPU and memory usage for each query. For more information, see system.query_log.

Troubleshooting memory limit errors

The ClickHouse server tracks memory usage at multiple levels. For a single query, a memory tracker aggregates the memory usage of all its query threads. This tracker then reports to an overall memory tracker. The solution depends on the specific error you encounter.

  • An error with Memory limit (for query) means the query failed because it consumed too much memory, exceeding its limit of 70% of the total instance memory capacity. To resolve this, perform a vertical upgrade to increase the instance memory capacity.

  • An error with Memory limit (for total) means the overall memory usage on the instance has exceeded the system-wide limit of 90% of the total instance memory capacity. This error can result from high query concurrency or resource-intensive background asynchronous tasks, such as primary key merge tasks that run after data writes. First, try reducing query concurrency. If the error persists, perform a vertical upgrade to increase the instance memory capacity.

Memory limit errors in enterprise clusters

Cause: The total number of ClickHouse Compute Units (CCUs) in an Alibaba Cloud ClickHouse Enterprise Edition cluster is the sum of the CCUs from all its nodes. A single node has a 32c128g specification, providing 32 CCUs and a 128 GB memory limit. This limit includes memory used by the operating system, leaving approximately 115 GB available. By default, SQL queries run on a single node. Therefore, if a query consumes more than 115 GB of memory, a memory limit error may occur.

Note

A cluster's node count depends only on its maximum CCU count. If the maximum CCU count is greater than 64, the number of nodes in an enterprise edition cluster is calculated as: Maximum CCU count / 32. If the maximum CCU count is less than 64, the enterprise edition cluster has 2 nodes.

Solution: To resolve this, append the following settings to your SQL statement. This enables the query to execute in parallel across multiple nodes, which can reduce the load on any single node and help prevent memory limit errors.

SETTINGS 
    allow_experimental_analyzer = 1,
    allow_experimental_parallel_reading_from_replicas = 1;

Resolve high memory consumption in GROUP BY operations

Set the max_bytes_before_external_group_by parameter to limit memory consumption by GROUP BY operations. Note that the allow_experimental_analyzer setting controls whether this parameter takes effect.

Handling Concurrency Limit Exceeded errors

The default maximum query concurrency for a server is 100. You can modify this value in the console. To modify the parameter's value, follow these steps:

  1. Log in to the ApsaraDB for ClickHouse console.

  2. On the Clusters page, select Clusters of Community-compatible Edition, and then click the target cluster ID.

  3. In the left-side navigation pane, click Parameter Configuration.

  4. On the Parameter Configuration page, click the edit icon in the Parameter Value column for the max_concurrent_queries parameter.

  5. Enter the new value in the dialog box and click OK.

  6. Click Submit Parameters.

  7. Click OK.

Inconsistent query results when data writes have stopped

Problem description: When you query data using select count(*), only about half of the total data is returned, or the results fluctuate.

Consider the following solutions.

  • Check if you are using a multi-node cluster. In a multi-node cluster, you must create a distributed table. Write to and query this table to ensure consistent results. Otherwise, each query may hit a different shard, leading to inconsistent results. For instructions, see Create a distributed table.

  • Check if you are using a master-replica cluster. In a master-replica cluster, you must use tables with a Replicated series table engine to synchronize data between replicas. Otherwise, each query may hit a different replica, leading to inconsistent results. To create tables with a Replicated series table engine, see Table engines.

Invisible tables and fluctuating query results

Common causes and solutions include:

  • Cause 1: The table creation process is incorrect. A ClickHouse distributed cluster does not have native distributed DDL semantics. If you use a create table statement in a self-managed ClickHouse cluster, the statement may return a success message, but the table is created only on the currently connected server. When you connect to a different server, the table is not visible.

    Solution:

    1. When you create a table, use the create table <table_name> on cluster default statement. The on cluster default clause broadcasts the statement to all nodes in the default cluster.

      CREATE TABLE test ON cluster default (a UInt64) Engine = MergeTree() ORDER BY tuple();
    2. Create another table that uses the distributed table engine on top of the test table.

      CREATE TABLE test_dis ON cluster default AS test Engine = Distributed(default, default, test, cityHash64(a));
  • Cause 2: The ReplicatedMergeTree table is misconfigured. The ReplicatedMergeTree table engine is an enhanced version of the MergeTree table engine that provides master-replica synchronization. On a single-replica instance, you can only create tables with the MergeTree engine. On a master-replica instance, you must create tables with the ReplicatedMergeTree engine.

    Solution: When you create a table in a master-replica instance, use ReplicatedMergeTree('/clickhouse/tables/{database}/{table}/{shard}', '{replica}') or ReplicatedMergeTree() to configure the ReplicatedMergeTree table engine. The arguments in ReplicatedMergeTree('/clickhouse/tables/{database}/{table}/{shard}', '{replica}') are part of a fixed template and should not be modified.

Timestamp data discrepancies

Run SELECT timezone() to check if the timezone is the local timezone. If not, set the 'timezone' configuration item to the local timezone. See Modify running parameter values for configuration items for instructions.

Table not found after creation

This issue commonly occurs when a DDL statement is executed on only one node.

To resolve this issue, ensure the DDL statement includes the on cluster clause. For more information, see table creation syntax.

No new data in Kafka external tables

First, run a select * from query on the Kafka external table. If the query fails, check the error message. This is often due to a data parsing failure. If the query returns results, check that the fields of the destination table (the underlying storage table for the Kafka external table) and the Kafka external table match. If the data write fails, the fields do not match. For example:

insert into <destination table> as select * from <Kafka external table>;

Client time and time zone mismatch

This issue occurs when the use_client_time_zone setting is configured with an incorrect time zone.

Data not visible after a write operation?

Symptom: After you write data to a table, subsequent queries cannot find the data.

Cause: Possible causes include the following:

  • The schemas of the distributed table and the local tables are inconsistent.

  • After data is written to a distributed table, the distribution of temporary files is incomplete.

  • After data is written to one replica in a master-replica cluster, replica synchronization is incomplete.

Analysis and solutions:

Inconsistent schemas

Query the system.distribution_queue system table to check for errors that occurred during writes to the distributed table.

Incomplete file distribution

Cause analysis: In a multi-node ApsaraDB for ClickHouse cluster, if your application connects to the database using a domain name and runs an INSERT statement on a distributed table, a front-end Server Load Balancer (SLB) routes the request to a random node in the cluster. The node that receives the request writes part of the data to its local disk and stores the rest as temporary files. These files are then asynchronously distributed to the other nodes. If a query is executed before this distribution process is complete, it may not return the undistributed data.

Solution: If your application requires strong read-after-write consistency, add the settings insert_distributed_sync = 1 clause to your INSERT statement. This setting switches the INSERT operation to a synchronous mode. The statement returns a success message only after the data is distributed to all nodes.

Important
  • Enabling this setting increases the execution time of INSERT statements because the operation must wait for data distribution to complete. Evaluate the trade-off between data consistency and write performance for your application.

  • This setting applies at the cluster level and should be used with caution. First, test this setting on a single query. After verifying the results, apply it at the cluster level only if your business requires it.

  • To apply this setting to a single query, append it to the end of the statement. For example:

    INSERT INTO <table_name> values() settings insert_distributed_sync = 1;
  • To apply this setting at the cluster level, configure it in the user.xml file. For more information, see Configure user.xml parameters.

Incomplete replica synchronization

Cause analysis: In a master-replica ApsaraDB for ClickHouse cluster, when you run an INSERT statement, the cluster executes the operation on one randomly chosen replica. The data is then asynchronously synchronized to the other replica. If a subsequent SELECT query is routed to the replica that has not yet completed synchronization, the query may not return the expected data.

Solution: If your application requires strong read-after-write consistency, add the settings insert_quorum = 2 clause to your INSERT statement. This setting forces replica synchronization to run in synchronous mode. The INSERT statement returns a success message only after data synchronization is complete on both replicas.

Important

Consider the following when you use this parameter:

  • This setting increases the execution time of INSERT statements because the operation must wait for replica synchronization to complete. Evaluate the trade-off between data consistency and write performance for your application.

  • After this parameter is set, INSERT operations must wait for synchronization between replicas to succeed. This means that if a replica is unavailable, all write operations configured with insert_quorum = 2 will fail, which conflicts with the reliability guarantee of a dual-replica setup.

  • This setting applies at the cluster level and should be used with caution. First, test this setting on a single query. After verifying the results, apply it at the cluster level only if your business requires it.

  • To apply this setting to a single query, append it to the end of the statement. For example:

    INSERT INTO <table_name> values() settings insert_quorum = 2;
  • To apply this setting at the cluster level, configure it in the user.xml file. For more information, see Configure user.xml parameters.

Why is TTL not deleting expired data?

Symptom

Even if you correctly configure a table's TTL, expired data may not be deleted, indicating the setting has not taken effect.

Troubleshooting steps

  1. Check if the table's TTL setting is reasonable.

    Set the TTL based on your business requirements. As a best practice, set the TTL at the day level. Avoid setting TTLs at the second or minute level, such as TTL event_time + INTERVAL 30 SECOND.

  2. Check the materialize_ttl_after_modify parameter.

    This parameter determines if a new TTL rule applies to existing data after you run an ALTER MODIFY TTL statement. A value of 1 (the default) enables it, meaning the rule applies to all data. A value of 0 applies the rule only to new data, leaving existing data unaffected.

    • Check the parameter

      SELECT * FROM system.settings WHERE name like 'materialize_ttl_after_modify';
    • Modify the parameter

      Important

      This command scans all existing data and can create a high resource load. Use it with caution.

      ALTER TABLE $table_name MATERIALIZE TTL;
  3. Diagnose the partition cleanup strategy.

    When the ttl_only_drop_parts parameter is set to 1, ClickHouse deletes a part only when all rows within that part have expired.

    • Check the ttl_only_drop_parts parameter

      SELECT * FROM system.merge_tree_settings WHERE name LIKE 'ttl_only_drop';
    • Check the partition expiration status

      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: The minimum date and time key value used for the TTL DELETE rule in this part.

      • delete_ttl_info_max: The maximum date and time key value used for the TTL DELETE rule in this part.

    • If the partition rule and the TTL rule do not align, some data might not be cleaned up in a timely manner. The following section describes how partition rules and TTL rules interact.

      • If the partition rule and the TTL rule are aligned (for example, both are daily), ClickHouse can determine expiration based on the partition ID and delete an entire partition at once. This is the most efficient strategy. For optimal performance, we recommend that you align your partitioning strategy (such as daily partitioning) with your TTL policy and set ttl_only_drop_parts=1 to efficiently delete expired data and improve performance.

      • If the rules are not aligned and ttl_only_drop_parts = 1, ClickHouse checks the TTL information and deletes a part only after its delete_ttl_info_max time has passed.

      • If the rules are not aligned and ttl_only_drop_parts = 0, ClickHouse must scan each part to find and delete individual expired rows, which is the most resource-intensive strategy.

  4. Manage the merge trigger frequency.

    Expired data is deleted asynchronously during data merges, not in real time. You can manage the merge frequency with the merge_with_ttl_timeout parameter or force a TTL operation by running the ALTER TABLE ... MATERIALIZE TTL statement.

    • Check the parameter

      SELECT * FROM system.merge_tree_settings WHERE name = 'merge_with_ttl_timeout';
      Note

      The unit is seconds. The default value on a production instance is 7,200 seconds (2 hours).

    • Modify the parameter

      If the value of merge_with_ttl_timeout is set too high, the TTL merge trigger frequency decreases, which causes expired data to remain for a long time. You can lower this parameter to increase the cleanup frequency. For more information, see Parameter Description.

  5. Check the thread pool parameter settings.

    ClickHouse performs TTL deletions during the part merge phase. The process is limited by the max_number_of_merges_with_ttl_in_pool (default value of 2 for a production instance) and background_pool_size (default value of 16 for a production instance) parameters.

    • Query current background thread activity

      SELECT * FROM system.metrics WHERE metric LIKE 'Background%';

      The BackgroundPoolTask metric provides a real-time value of the tasks running in the background pool, which is limited by the background_pool_size setting.

    • Modify parameters

      If your other parameter settings are correct and CPU resources are available, try increasing the max_number_of_merges_with_ttl_in_pool parameter from 2 to 4, or 4 to 8. If the issue persists, increase the background_pool_size parameter.

      Important

      You must restart the cluster if you adjust the max_number_of_merges_with_ttl_in_pool parameter or decrease the background_pool_size parameter. A restart is not required if you increase the background_pool_size parameter.

  6. Check if the table structure and partition design are reasonable.

    If a table is not partitioned reasonably or if the partition granularity is too coarse, TTL cleanup efficiency decreases. To efficiently clean up expired data, align the granularity of your partitions with the granularity of your TTL (for example, use daily for both). For more information, see Best Practices.

  7. Check if the cluster has sufficient disk space.

    Background merge operations trigger TTL deletions, which require temporary disk space. If large part files exist or disk space is low (for example, usage exceeds 90%), merge operations and their associated TTL deletions may fail.

  8. Check other system parameter settings in system.merge_tree_settings.

    • merge_with_recompression_ttl_timeout: The minimum delay before a merge with recompression TTL is repeated. The default value for a production instance is 4 hours. By default, ClickHouse applies TTL rules to a table at least every 4 hours. If you need to apply TTL rules more frequently, modify this setting.

    • max_number_of_merges_with_ttl_in_pool: This parameter sets the maximum number of threads for TTL tasks. If the number of ongoing TTL merge tasks in the background thread pool reaches this limit, ClickHouse assigns no new TTL merge tasks.

Slow optimize tasks

An optimize task is CPU- and disk throughput-intensive. It can conflict with concurrent queries, as both compete for the same system resources. Consequently, an optimize task may run slowly when the node is under a heavy load. No specific optimization method is currently available.

Primary key merge failure after optimize

A primary key merge must meet the following two prerequisites to function correctly.

  • The ORDER BY key must include the partition key of the storage table. A primary key merge does not occur across different partitions.

  • For a distributed table, the ORDER BY key must include the sharding key, which is determined by the hash algorithm. A primary key merge does not occur across different nodes.

The following table describes common optimize commands and their behavior.

Command

Description

optimize table test;

This command attempts to select and merge MergeTree data parts but may return without performing any action. Even if executed, it does not guarantee a complete primary key merge for all records in the table. This command is generally not recommended.

optimize table test partition tuple();

This command targets a specific partition and merges all its data parts. It may return without performing any action. When the task finishes, it consolidates all data within the specified partition into a single data part, completing the primary key merge for that partition. However, the merge does not include data written while the task is running. The task does not run again if the partition already consists of a single data part.

Note

For tables without a partition key, the default partition is tuple().

optimize table test final;

This command forces a merge of all partitions in the table. It re-merges partitions even if they already consist of a single data part. This is useful for forcing the deletion of records that have exceeded their Time to Live (TTL). This operation is the most resource-intensive and may still return without performing a merge.

For any of these optimize commands, you can set the optimize_throw_if_noop parameter. If this parameter is enabled, the command throws an exception if it performs no merge, so you can determine whether the task was actually performed.

Data TTL ineffective after optimize

Here are common causes and their solutions.

  • Cause 1: Data TTL eviction occurs during the primary key merge phase. If a data part is not merged for an extended period, the system cannot evict the expired data within it.

    Solution:

    • You can manually trigger a merge task by running optimize final or optimize a specific partition.

    • When creating a table, you can set parameters such as merge_with_ttl_timeout and ttl_only_drop_parts to merge data parts that contain expired data more frequently.

  • Cause 2: If a table's TTL is modified or added, existing data parts may have missing or incorrect TTL information. This may also prevent the eviction of expired data.

    Solution:

    • You can regenerate TTL information by running alter table materialize ttl.

    • You can update the TTL information by running optimize partition.

Updates and deletes not taking effect after OPTIMIZE

ApsaraDB for ClickHouse executes update and delete operations asynchronously. While you cannot directly control this process, you can monitor its progress by querying the system.mutations system table.

Adding, deleting, or modifying columns with DDL

To modify a local table, execute a DDL statement. For a distributed table, the procedure depends on whether data is currently being written to it.

  • If no data is being written to the table, modify the local table first, and then modify the distributed table.

  • If data is being written to the table, the procedure depends on the type of modification.

    Type

    Actions

    Adding a nullable column

    1. Modify the local table.

    2. Modify the distributed table.

    Modifying a column's data type (to a convertible type)

    Dropping a nullable column

    1. Modify the distributed table.

    2. Modify the local table.

    Adding a non-nullable column

    1. Stop writing data.

    2. Execute SYSTEM FLUSH DISTRIBUTED on the distributed table.

    3. Modify the local table.

    4. Modify the distributed table.

    5. Resume writing data.

    Dropping a non-nullable column

    Renaming a column

Slow and stuck DDL operations

This is often because global DDL execution is sequential, and complex queries can cause deadlocks.

Try the following solutions.

  • Wait for the operation to complete.

  • Try terminating the query in the console.

Distributed DDL task timeout error

You can modify the default timeout by using the set global on cluster default distributed_ddl_task_timeout=xxx command, where xxx is the custom timeout in seconds. For more information about modifying global parameters, see Modify cluster parameters.

Syntax error: "set global on cluster default"

  • Cause 1: The ClickHouse client parses syntax. However, set global on cluster default is a server-side syntax. If the client version is incompatible with the server, the client blocks this statement.

    Solution:

    • Use a tool that does not perform client-side syntax parsing. Examples include JDBC-based tools like DataGrip and DBeaver.

    • Write a JDBC program to execute the statement.

  • Cause 2: In the set global on cluster default key = value; statement, the value is a string but is not enclosed in quotation marks.

    Solution: Enclose the string value in quotation marks.

Recommended BI tool

We recommend Quick BI.

Recommended data query IDEs

DataGrip, DBeaver.

Vector search support

Yes. ApsaraDB for ClickHouse supports vector search. For more information, see the following documents:

Resolve the ON CLUSTER is not allowed for Replicated database error

If your cluster is an Enterprise Edition cluster and the table creation statement includes ON CLUSTER default, you may encounter the ON CLUSTER is not allowed for Replicated database error. This issue occurs in some minor versions. To resolve it, upgrade your instance to the latest version. For instructions, see Upgrade minor engine versions.

Resolve the Double-distributed IN/JOIN subqueries is denied (distributed_product_mode = 'deny') error

Problem: If you use a multi-node Community Edition cluster, you might encounter the errorException: Double-distributed IN/JOIN subqueries is denied (distributed_product_mode = 'deny').  when a query uses JOIN or IN to join multiple distributed tables.

Cause: When a query joins multiple distributed tables, it can cause query amplification. For example, in a three-node cluster, a join query between two distributed tables expands into 3 x 3 subqueries on the underlying local tables. This consumes significant resources and increases latency. To prevent this, the system blocks these queries by default.

How it works: By replacing the IN or JOIN operator with GLOBAL IN or GLOBAL JOIN, you instruct the engine to execute the right-side subquery on a single node. The result is stored in a temporary table, which is then broadcast to all other nodes to complete the join locally.

Impact of using GLOBAL IN or GLOBAL JOIN:

  • The temporary table is sent to all remote servers. Avoid this strategy for large datasets.

  • Using GLOBAL IN or GLOBAL JOIN with the remote() function can produce incorrect results. This is because the subquery, which should run on the external instance, instead runs on the current instance.

    For example, you run the following statement on instance_a to query data from the external instance 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);

    In this case, instance_a executes the subquery SELECT id FROM test_tbl_distributed1 to generate a temporary table, let's call it temp_table_A. The data from temp_table_A is then sent to the external instance cc-bp1wc089c**** for the final query. The external instance cc-bp1wc089c**** ultimately runs the statement SELECT * FROM default.test_tbl_distributed1 WHERE id IN (temp_table_A);.

    The problem arises from the source of the data in the temporary table.

    Based on the description above, the final statement executed by instance cc-bp1wc089c**** is SELECT * FROM default.test_tbl_distributed1 WHERE id IN (temporary table A);. However, the condition set in temporary table A is generated on instance a. In this example, instance cc-bp1wc089c**** should have executed SELECT * FROM default.test_tbl_distributed1 WHERE id IN (SELECT id FROM test_tbl_distributed1 );, and the condition set should have originated from instance cc-bp1wc089c****. Therefore, the use of GLOBAL IN or GLOBAL JOIN causes the subquery to retrieve the condition set from an incorrect source, which leads to an incorrect result.

Solutions:

Solution 1: Modify your application's SQL code to manually replace IN or JOIN with GLOBAL IN or GLOBAL JOIN.

For example, change this statement:

SELECT * FROM test_tbl_distributed WHERE id IN (SELECT id FROM test_tbl_distributed1);

to:

SELECT * FROM test_tbl_distributed WHERE id GLOBAL IN (SELECT id FROM test_tbl_distributed1);

Solution 2: Modify the distributed_product_mode or prefer_global_in_and_join system parameter so the system automatically converts IN or JOIN to GLOBAL IN or GLOBAL JOIN.

distributed_product_mode

Run the following statement to set distributed_product_mode to global. This setting automatically converts standard IN or JOIN operations into GLOBAL IN or GLOBAL JOIN when necessary.

SET GLOBAL ON cluster default distributed_product_mode='global';

Usage

  • Purpose: Controls how ClickHouse handles distributed subqueries.

  • Values:

    • deny (default): Prohibits distributed IN and JOIN subqueries and throws the "Double-distributed IN/JOIN subqueries is denied" exception.

    • local: Rewrites the subquery to use the local table on the target shard, preserving a standard IN or JOIN operator.

    • global: Converts IN or JOIN queries to GLOBAL IN or GLOBAL JOIN queries.

    • allow: Permits standard IN and JOIN subqueries, which may cause query amplification.

  • Applicable scenarios: Applies only to queries that use IN or JOIN to join multiple distributed tables.

prefer_global_in_and_join

prefer_global_in_and_join

Run the following statement to set the prefer_global_in_and_join parameter to 1. This setting automatically converts standard IN or JOIN operations into GLOBAL IN or GLOBAL JOIN.

SET GLOBAL ON cluster default prefer_global_in_and_join = 1;

Usage

  • Purpose: Controls the behavior of the IN and JOIN operators.

  • Values:

    • 0 (default): Prohibits distributed IN and JOIN subqueries and throws the "Double-distributed IN/JOIN subqueries is denied" exception.

    • 1: Enables distributed IN and JOIN subqueries by automatically converting them to GLOBAL IN or GLOBAL JOIN queries.

  • Applicable scenarios: Applies only to queries that use IN or JOIN to join multiple distributed tables.

View table disk space

To view the disk space used by each table, run the following query.

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; 

View cold data size

The following is an example query:

SELECT * FROM system.disks;

Query data in cold storage

Use the following query:

SELECT * FROM system.parts WHERE disk_name = 'cold_disk';

Move partition data to cold storage

To move a data partition to cold storage, run the following statement:

ALTER TABLE table_name MOVE PARTITION partition_expr TO DISK 'cold_disk';

Gaps in monitoring data

Common causes include:

  • A query triggering an OOM error.

  • An instance restart triggered by a configuration change.

  • An instance restart following an upgrade or downgrade.

Smooth upgrade without data migration

Whether a ClickHouse cluster supports a smooth upgrade depends on its creation date. Clusters purchased after December 1, 2021 support an in-place smooth upgrade to a new major engine version without data migration. Clusters purchased before December 1, 2021 require data migration to upgrade to a new major engine version. For upgrade instructions, see Upgrade the major engine version.

Common system tables

The following table describes common system tables and their functions.

Parameter

Description

system.processes

Contains information about SQL statements that are currently running.

system.query_log

Contains a log of executed SQL statements.

system.merges

Contains information about merge operations on the cluster.

system.mutations

Contains information about mutation operations on the cluster.

Modify system-level parameters

System-level parameters map to settings in the config.xml file. To modify these parameters, follow these steps.

  1. Log in to the ApsaraDB for ClickHouse console.

  2. On the Clusters page, select Clusters of Community-compatible Edition, and then click the target cluster ID.

  3. In the left-side navigation pane, click Parameter Configuration.

  4. On the Parameter Configuration page, click the edit icon in the Parameter Value column for the max_concurrent_queries parameter.

  5. Enter the new value in the dialog box and click OK.

  6. Click Submit Parameters.

  7. Click OK.

After clicking OK, the clickhouse-server process automatically restarts, causing a transient disconnection of about 1 minute.

Modify user-level parameters

User-level parameters correspond to configuration items in the users.xml file. To modify a parameter, run the following statement.

SET global ON cluster default ${key}=${value};

Unless specified otherwise, the change takes effect immediately.

Modify quota

Specify the quota parameter in the settings of an execution statement:

settings max_memory_usage = XXX;

Varying CPU and memory usage across nodes

In a dual-replica or single-replica multi-node cluster, the write node has higher CPU usage and memory usage than other nodes during heavy write operations. Usage balances out across the nodes once the data is synchronized.

View detailed system logs

  • Problem description:

    How to view detailed system logs to troubleshoot errors or identify potential issues.

  • Solution:

    1. Check the text_log.level parameter for your cluster and do one of the following:

      1. If text_log.level is empty, text logging is disabled. To enable it, set a value for this parameter.

      2. If text_log.level has a value, verify that the log level meets your requirements. If not, modify the parameter to the desired level.

      To view and modify the text_log.level parameter, see Configure config.xml parameters.

    2. Connect to the target database. For details, see Connect to a database.

    3. Run the following statement to view and analyze the logs.

      SELECT * FROM system.text_log;

Resolve network connectivity issues

If the destination cluster and data source are in the same VPC and region, verify that the IP address of each is in the other's whitelist.

  • To set a whitelist in ClickHouse, see Set a Whitelist.

  • For other data sources, see their respective product documentation.

If the preceding conditions are not met, first establish connectivity by using a suitable network solution. Then, add the IP address of each to the other's whitelist.

Scenario

Solution

hybrid cloud connectivity

Network Interconnection Between On-Premises and Cloud

cross-region and cross-account VPC connectivity

Cross-account VPC-to-VPC Connection

same-region, different-VPC connectivity

Use Cloud Enterprise Network to Achieve Same-region VPC Connectivity (Basic Edition)

cross-region and cross-account VPC connectivity

Use Cloud Enterprise Network to Achieve Cross-region and Cross-account VPC-to-VPC Connection (Basic Edition)

public network connectivity

Use Internet NAT Gateway SNAT to Access the Internet

address conflict

Use VPC NAT Gateway to Resolve Address Conflicts

Community to Enterprise Edition migration

Yes, you can migrate a ClickHouse Community Edition cluster to an Enterprise Edition cluster.

You can migrate data between Enterprise Edition and Community Edition clusters in two main ways: using the remote function or exporting and importing data files. For detailed instructions, see Migrate data from a self-managed ClickHouse cluster to Alibaba Cloud ClickHouse Community-Compatible Edition.

Inconsistent schemas during data migration

Problem description

Data migration requires consistent database and table schemas across all shards. Otherwise, some databases or tables may fail to migrate.

Solutions

  • The schema of a MergeTree table (not an inner table of a materialized view) is inconsistent across shards.

    Investigate whether your business logic is causing the schema discrepancies between shards:

    • If you expect the table schemas to be identical across all shards, you must recreate the tables to ensure consistency.

    • If your business logic intentionally uses different table schemas across shards, Submit a ticket to contact technical support for assistance.

  • The inner table of a materialized view is inconsistent across shards.

    • Solution 1: Rename the inner tables and explicitly point the materialized view and distributed table to the target MergeTree table. The following procedure uses the original materialized view up_down_votes_per_day_mv as an example.

      1. List tables that are not present on every node. NODE_NUM = Number of shards × Number of replicas.

        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>;
      2. Identify the materialized views that have an incorrect number of inner tables.

        SELECT substring(hostName(),38,8) AS host,*
        FROM cluster(default, system.tables)
        WHERE uuid IN (<UUID1>, <UUID2>, ...);
      3. Disable the default cluster synchronization behavior. This step is required for ApsaraDB for ClickHouse clusters but not for self-managed ClickHouse clusters. Then, rename the inner table to ensure consistency across all nodes. To reduce operational risk, obtain the IP address of each node, connect to port 3005, and run the following statements on each node individually.

        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`;
      4. Drop the materialized view. Run the following statements on each node individually.

        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;
      5. Create a new materialized view that explicitly points to the renamed inner table. Run the following statements on each node individually.

        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;

        Note: You must explicitly define the columns of the target table in the materialized view definition. Do not rely on type inference from the SELECT statement, as this can cause unexpected errors. For example, if a column named tcp_cn is calculated using an aggregate state function like sumIfState in the SELECT statement, you must define its type in the target table as an AggregateFunction, such as AggregateFunction(sum, Float64).

        Correct usage

        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
        ...

        Incorrect usage

        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
        ...
    • Solution 2: Rename the inner tables, rebuild the materialized views on all nodes, and then migrate the data from the old inner tables.

    • Solution 3: Implement a dual-write strategy for the materialized views and allow 7 days for the data to synchronize.

SQL statement failure in Enterprise Edition 24.5 or later

By default, Enterprise Edition 24.5 or later instances use the new analyzer in their query engine. This new analyzer delivers better query performance but may not be backward-compatible with some legacy SQL statements, causing a parsing error. If you encounter this error, run the following statement to revert to the legacy analyzer. For more information, see Learn more about the new analyzer.

SET allow_experimental_analyzer = 0;

Suspend a cluster

The suspend feature is only available for Enterprise Edition clusters. ClickHouse Community Edition clusters cannot be suspended. To suspend an Enterprise Edition cluster, go to the Enterprise Edition Clusters page. Select the target region in the top-left corner. In the cluster list, find the target cluster and click image> Suspend in the Actions column.

Convert a MergeTree table to ReplicatedMergeTree

Problem description

Users unfamiliar with ClickHouse may mistakenly create tables with the MergeTree engine in a multi-replica cluster. This prevents data from being synchronized between the replica nodes of each shard. Consequently, queries on the corresponding distributed table can return inconsistent results. To resolve this issue, you must convert the MergeTree table to a ReplicatedMergeTree table.

Solution

ClickHouse does not provide a DDL statement to directly change a table's storage engine. To convert a MergeTree table to a ReplicatedMergeTree table, you must create a new table with the ReplicatedMergeTree engine and then import the data from the original table.

For example, assume you have a MergeTree table named table_src and its corresponding distributed table named table_src_d in a multi-replica cluster. To convert this MergeTree table to a ReplicatedMergeTree table, follow these steps:

  1. Create the target ReplicatedMergeTree table, table_dst, and its corresponding distributed table, table_dst_d. For more information, see CREATE TABLE.

  2. Import the data from the MergeTree table table_src into table_dst_d. You can use one of the following two methods.

Note
  • Both methods query source data from the local MergeTree table.

  • If the data volume is small, insert data directly into the distributed table table_dst_d to distribute the data evenly.

  • If the data in the original MergeTree table table_src is already balanced across all nodes and the data volume is large, you can insert the data directly into the local ReplicatedMergeTree table table_dst on each node.

  • If the dataset is large, the import process may take a long time. When you use the remote() function, make sure to configure an appropriate timeout value.

Use the remote function

  1. Connect to ClickHouse through DMS.

  2. Obtain the IP address of each node.

    SELECT 
        cluster,
        shard_num,
        replica_num,
        is_local,
        host_address
    FROM system.clusters
    WHERE cluster = 'default';
    
  3. Import the data by using the remote function.

    Sequentially pass the IP addresses from the previous step to the remote() function and run the statement for each.

    INSERT INTO  table_dst_d SELECT * FROM remote('node1', db.table_src) ;

    For example, if the IP addresses of two nodes are 10.10.0.165 and 10.10.0.167, run the following INSERT statements separately:

    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) ;

    Running the statements for all node IP addresses converts the MergeTree table to a ReplicatedMergeTree table.

Use local tables

If you have an ECS instance with the ClickHouse client installed in your VPC, you can log on to each node separately to perform the following operations.

  1. Connect to ClickHouse using the command line interface.

  2. Obtain the IP address of each node.

    SELECT 
        cluster,
        shard_num,
        replica_num,
        is_local,
        host_address
    FROM system.clusters
    WHERE cluster = 'default';
  3. Import the data.

    Log on to each node sequentially by using its IP address and run the following statement.

    INSERT INTO table_dst_d SELECT * FROM db.table_src ;

    Running the statement on all nodes converts the MergeTree table to a ReplicatedMergeTree table.

Execute multiple SQL statements in the same session

Setting a unique session_id ensures the ClickHouse server maintains a consistent context for requests with the same session ID. This lets you execute multiple SQL statements in a single session. This example shows how to do this with the ClickHouse Java Client (V2).

  1. Add the dependency to the pom.xml file of your Maven project.

    <dependency>
        <groupId>com.clickhouse</groupId>
        <artifactId>client-v2</artifactId>
        <version>0.8.2</version>
    </dependency>
  2. Set a custom session ID in CommandSettings.

    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") // Instance endpoint
                    .setUsername("username")   // Username
                    .setPassword("password")   // Password
                    .build();
    
            try {
                client.ping(10);
                CommandSettings commandSettings = new CommandSettings();
                // Set the session_id
                commandSettings.serverSetting("session_id","examplesessionid");
                // Set the max_block_size parameter for the session
                client.execute("SET max_block_size=65409 ",commandSettings);
                // Execute the queries
                client.execute("SELECT 1 ",commandSettings);
                client.execute("SELECT 2 ",commandSettings);
    
            } catch (Exception e) {
                throw new RuntimeException(e);
            } finally {
                client.close();
            }
        }
    }

In this example, both SELECT statements run in the same session with a max_block_size of 65409. For more information about using the ClickHouse Java Client, see Java Client | ClickHouse Docs.

Why FINAL deduplication fails with JOIN

Symptom

When you use the FINAL keyword to deduplicate query results, deduplication fails if the SQL statement contains a JOIN clause. As a result, duplicate data remains in the output. The following is an example SQL statement:

SELECT * FROM t1 FINAL JOIN t2 FINAL WHERE xxx;

Cause

This is a known, unpatched bug in ClickHouse. Deduplication fails because of a conflict between the execution logic of FINAL and JOIN. For more information, see ClickHouse's issues.

Solution

  • Solution 1 (Recommended): Enable the experimental optimizer. Enable query-level FINAL by adding a setting to your query. This method does not require a table-level declaration. For example:

    If the original SQL statement is:

    SELECT * FROM t1 FINAL JOIN t2 FINAL WHERE xxx;

    Remove the FINAL keyword from the table name and append settings allow_experimental_analyzer = 1,FINAL = 1 to the statement. The revised statement is as follows:

    SELECT * FROM t1 JOIN t2 WHERE xxx  SETTINGS allow_experimental_analyzer = 1, FINAL = 1; 
    Important

    The allow_experimental_analyzer parameter is supported only in versions 23.8 and later. If you use a version earlier than 23.8, we recommend that you upgrade the version before you modify the SQL statement. For more information about how to perform an upgrade, see Upgrade a major engine version.

  • Solution 2 (Use with caution):

    1. Force a merge for deduplication by periodically running OPTIMIZE TABLE local_table_name FINAL. This merges data in advance but should be used with caution for large tables, as it incurs high I/O overhead.

    2. Modify the SQL query: Remove the FINAL keyword. Data deduplication then relies on querying the merged data.

    Important

    Use this approach with caution because this operation consumes significant I/O resources and can affect the performance of large tables.

Why are DELETE or UPDATE operations incomplete?

Symptom

When you perform data deletion (DELETE) or update (UPDATE) operations in an ApsaraDB for ClickHouse Community-compatible Edition cluster, the tasks remain incomplete for a long time.

Cause

Unlike synchronous operations in MySQL, the DELETE and UPDATE operations in an ApsaraDB for ClickHouse Community-compatible Edition cluster are asynchronous and are executed based on the Mutation mechanism. Therefore, the changes do not take effect in real time. The core process of a Mutation is as follows:

  1. Submit task: A user runs the ALTER TABLE ... UPDATE/DELETE command to generate an asynchronous task.

  2. Mark data: The system creates a mutation_*.txt file in the background to record the data range to be modified. The changes are not applied immediately.

  3. Rewrite in the background: ClickHouse gradually rewrites the affected data part and applies the changes during the merge process.

  4. Clean up old data: After the merge is complete, the old data blocks are marked for deletion.

Therefore, issuing too many Mutation operations in a short period can block tasks and leave DELETE and UPDATE operations incomplete. To prevent a backlog, run the following SQL statement to check for running Mutations before you issue a new one.

SELECT * FROM clusterAllReplicas('default', system.mutations) WHERE is_done = 0;

Solution

  1. Check whether an excessive number of Mutation tasks are running on the cluster.

    You can run the following SQL statement to view the current status of Mutations in the cluster:

    SELECT * FROM clusterAllReplicas('default', system.mutations) WHERE is_done = 0;
  2. If many Mutation tasks are running, use a privileged account to cancel some or all of them.

    • Cancel all Mutation tasks on a single table.

      KILL MUTATION WHERE database = 'default' AND table = '<table_name>'
    • Cancel a specific Mutation task.

      KILL MUTATION WHERE database = 'default' AND table = '<table_name>' AND mutation_id = '<mutation_id>'

      To obtain the mutation_id, run the following SQL statement:

      SELECT mutation_id, * FROM clusterAllReplicas('default', system.mutations) WHERE is_done = 0;

Symptom

When you perform data deletion (DELETE) or update (UPDATE) operations in an ApsaraDB for ClickHouse Community-compatible Edition cluster, the tasks remain incomplete for a long time.

Cause

Unlike synchronous operations in MySQL, the DELETE and UPDATE operations in an ApsaraDB for ClickHouse Community-compatible Edition cluster are asynchronous and are executed based on the Mutation mechanism. Therefore, the changes do not take effect in real time. The core process of a Mutation is as follows:

  1. Submit task: A user runs the ALTER TABLE ... UPDATE/DELETE command to generate an asynchronous task.

  2. Mark data: The system creates a mutation_*.txt file in the background to record the data range to be modified. The changes are not applied immediately.

  3. Rewrite in the background: ClickHouse gradually rewrites the affected data part and applies the changes during the merge process.

  4. Clean up old data: After the merge is complete, the old data blocks are marked for deletion.

Therefore, issuing too many Mutation operations in a short period can block tasks and leave DELETE and UPDATE operations incomplete. To prevent a backlog, run the following SQL statement to check for running Mutations before you issue a new one.

SELECT * FROM clusterAllReplicas('default', system.mutations) WHERE is_done = 0;

Solution

  1. Check whether an excessive number of Mutation tasks are running on the cluster.

    You can run the following SQL statement to view the current status of Mutations in the cluster:

    SELECT * FROM clusterAllReplicas('default', system.mutations) WHERE is_done = 0;
  2. If many Mutation tasks are running, use a privileged account to cancel some or all of them.

    • Cancel all Mutation tasks on a single table.

      KILL MUTATION WHERE database = 'default' AND table = '<table_name>'
    • Cancel a specific Mutation task.

      KILL MUTATION WHERE database = 'default' AND table = '<table_name>' AND mutation_id = '<mutation_id>'

      To obtain the mutation_id, run the following SQL statement:

      SELECT mutation_id, * FROM clusterAllReplicas('default', system.mutations) WHERE is_done = 0;

How to resolve the ApsaraDB for ClickHouse Enterprise Edition error "Code: 241. DB::Exception: Memory limit (total) exceeded"?

  • Symptom: When you execute an SQL statement, you encounter the following error message, even though the total memory of your cluster exceeds the memory limit specified in the error message:

    Code: 241. DB::Exception: Memory limit (total) exceeded: would use 115.28 GiB (attempt to allocate chunk of 133791376 bytes), maximum: 115.20 GiB. OvercommitTracker decision: Query was selected to stop by OvercommitTracker.: While executing AggregatingTransform. (MEMORY_LIMIT_EXCEEDED) (version 24.2.2.16476 (official build))
  • Cause: In ApsaraDB for ClickHouse Enterprise Edition, a single node has a CCU limit (maximum of 32 CCUs, where 1 CCU is approximately equal to 1 vCore and 4 GiB of memory). If a single SQL query consumes more memory than the node's threshold, MemoryTracker intercepts the query. The default threshold is 0.9 times the total memory of the node. You can run the following SQL statement to query the threshold:

    SELECT *
    FROM system.server_settings
    WHERE name = 'max_server_memory_usage_to_ram_ratio';
  • Solution: You can set the allow_experimental_parallel_reading_from_replicas parameter to 1. This setting distributes the data reading phase of the SQL query across multiple nodes, which spreads the memory consumption. For more information about how to set this parameter, see Enterprise Edition.

Why are query results inconsistent?

Symptom

In an ApsaraDB for ClickHouse Community-compatible Edition cluster, running the same SQL statement multiple times returns inconsistent results.

Cause

Inconsistent results for the same query in an ApsaraDB for ClickHouse Community-compatible Edition cluster can occur for two main reasons:

  • Queries target a local table in a multi-shard cluster.

    In a multi-shard cluster of ApsaraDB for ClickHouse Community-compatible Edition, you must create a distributed table in addition to local tables. In such clusters, the data write process is as follows:

    Data is first written to the distributed table, which then distributes the data to local tables on different shards for storage.

    When you query data, the data source varies based on the type of table being queried:

    • Querying a distributed table: The distributed table aggregates and returns data from the local tables on all shards.

    • Querying a local table: Each query returns data from the local table of a randomly selected shard, which causes inconsistent results.

  • A table in a two-replica cluster was not created by using a Replicated* series engine.

    In a two-replica cluster of ApsaraDB for ClickHouse Community-compatible Edition, tables must be created with a Replicated* series engine, such as the ReplicatedMergeTree engine, to enable data synchronization between replicas.

    If a table in a two-replica cluster is created without a Replicated* series engine, data is not synchronized between replicas, which can cause inconsistent query results.

Solution

  1. Determine the cluster type.

    Check the cluster information to determine whether your cluster is a multi-shard cluster, a two-replica cluster, or a multi-shard and two-replica cluster. Follow these steps:

    1. Log on to the ApsaraDB for ClickHouse console.

    2. In the upper-left corner of the page, select clusters of Community-compatible Edition.

    3. In the cluster list, click the ID of the target cluster to open the cluster information page.

      View the Series in the Cluster Properties section and the number of node groups in the Configuration Information section. You can determine the cluster type based on the following properties:

      • If the number of node groups is greater than 1, the cluster is a multi-shard cluster.

      • If the series is High-availability Edition, the cluster is a two-replica cluster.

      • If both conditions are met, the cluster is a multi-shard and two-replica cluster.

  2. Select a solution based on the cluster type.

    Multi-shard cluster

    Check the type of the queried table. If it is a local table, query the distributed table instead.

    If a distributed table does not exist, you must create one. For more information, see Create a table.

    Two-replica cluster

    Check the CREATE TABLE statement for the target table. If its engine is not a Replicated* series engine, you must recreate the table. For more information, see Create a table.

    Multi-shard and two-replica cluster

    Check the type of the queried table.

    If it is a local table, query the distributed table. If a distributed table does not exist, you must create one.

    If you are querying a distributed table, check whether the engine of the corresponding local table is a Replicated* series engine. If not, you must recreate the local table and specify a Replicated* series engine. For more information, see Create a table.

Symptom

In an ApsaraDB for ClickHouse Community-compatible Edition cluster, running the same SQL statement multiple times returns inconsistent results.

Cause

Inconsistent results for the same query in an ApsaraDB for ClickHouse Community-compatible Edition cluster can occur for two main reasons:

  • Queries target a local table in a multi-shard cluster.

    In a multi-shard cluster of ApsaraDB for ClickHouse Community-compatible Edition, you must create a distributed table in addition to local tables. In such clusters, the data write process is as follows:

    Data is first written to the distributed table, which then distributes the data to local tables on different shards for storage.

    When you query data, the data source varies based on the type of table being queried:

    • Querying a distributed table: The distributed table aggregates and returns data from the local tables on all shards.

    • Querying a local table: Each query returns data from the local table of a randomly selected shard, which causes inconsistent results.

  • A table in a two-replica cluster was not created by using a Replicated* series engine.

    In a two-replica cluster of ApsaraDB for ClickHouse Community-compatible Edition, tables must be created with a Replicated* series engine, such as the ReplicatedMergeTree engine, to enable data synchronization between replicas.

    If a table in a two-replica cluster is created without a Replicated* series engine, data is not synchronized between replicas, which can cause inconsistent query results.

Solution

  1. Determine the cluster type.

    Check the cluster information to determine whether your cluster is a multi-shard cluster, a two-replica cluster, or a multi-shard and two-replica cluster. Follow these steps:

    1. Log on to the ApsaraDB for ClickHouse console.

    2. In the upper-left corner of the page, select Clusters of Community-compatible Edition.

    3. In the cluster list, click the ID of the target cluster to open the cluster information page.

      View the Edition in the Cluster Properties section and the Node Groups in the Configuration Information section. You can determine the cluster type based on the following properties:

      • If the number of node groups is greater than 1, the cluster is a multi-shard cluster.

      • If the series is High-availability Edition, the cluster is a two-replica cluster.

      • If both conditions are met, the cluster is a multi-shard and two-replica cluster.

  2. Select a solution based on the cluster type.

    Multi-shard cluster

    Check the type of the queried table. If it is a local table, query the distributed table instead.

    If a distributed table does not exist, you must create one. For more information, see Create a table.

    Two-replica cluster

    Check the CREATE TABLE statement for the target table. If its engine is not a Replicated* series engine, you must recreate the table. For more information, see Create a table.

    Multi-shard and two-replica cluster

    Check the type of the queried table.

    If it is a local table, query the distributed table. If a distributed table does not exist, you must create one.

    If you are querying a distributed table, check whether the engine of the corresponding local table is a Replicated* series engine. If not, you must recreate the local table and specify a Replicated* series engine. For more information, see Create a table.

Why ReplacingMergeTree fails deduplication after a forced merge?

Symptom

The ReplacingMergeTree engine in ClickHouse deduplicates data with the same primary key during the data merge process. However, after you force a data merge by running the following command, duplicate data with the same primary key may still exist:

optimize TABLE <table_name> FINAL ON cluster default;

Cause

The ReplacingMergeTree engine deduplicates data only on a single node. If data with the same primary key is distributed to different nodes because the sharding_key expression is not explicitly specified (by default, data is randomly allocated by using the rand() function), the engine cannot deduplicate the data across the cluster.

Solution

Recreate the local table and the distributed table. When you create the distributed table, set the sharding_key expression to the primary key of the local table. For more information about the table creation syntax, see CREATE TABLE.

Important

You must recreate both the distributed table and the local table. Recreating only the distributed table affects only new data, leaving existing data unduplicated.

Symptom

The ReplacingMergeTree engine in ClickHouse deduplicates data with the same primary key during the data merge process. However, after you force a data merge by running the following command, duplicate data with the same primary key may still exist:

optimize TABLE <table_name> FINAL ON cluster default;

Cause

The ReplacingMergeTree engine deduplicates data only on a single node. If data with the same primary key is distributed to different nodes because the sharding_key expression is not explicitly specified (by default, data is randomly allocated by using the rand() function), the engine cannot deduplicate the data across the cluster.

Solution

Recreate the local table and the distributed table. When you create the distributed table, set the sharding_key expression to the primary key of the local table. For more information about the table creation syntax, see CREATE TABLE.

Important

You must recreate both the distributed table and the local table. Recreating only the distributed table affects only new data, leaving existing data unduplicated.