Flink Connector
StarRocks provides an Apache Flink connector, hereafter referred to as the Flink Connector, to import data from Flink into StarRocks tables. The StarRocks Flink Connector delivers better performance and stability than Flink's built-in flink-connector-jdbc, which makes it ideal for large-scale data import scenarios.
Background information
The StarRocks Flink Connector caches mini-batches of data in memory and uses StarRocks' Stream Load feature for batch imports. It supports the DataStream API, Table API & SQL, and Python API, which significantly improves data import efficiency.
Prerequisites
-
You have created a cluster with the Flink service enabled.
This topic uses a DataFlow cluster with the Flink service created on EMR on ECS, hereafter referred to as a Flink cluster, as an example. For more information, see Create a cluster.
-
You have created an EMR Serverless StarRocks instance. For more information, see Create an instance.
Limits
-
Ensure that the machine running Flink can access the http_port (default
8030) and query_port (default9030) of the FE nodes, and the be_http_port (default8040) of the BE nodes in the StarRocks instance. -
To use the Flink Connector to import data into StarRocks, you need `SELECT` and `INSERT` permissions on the target table.
-
The Flink Connector has the following compatibility requirements with Java, Scala, and Flink versions.
Connector
Flink
StarRocks
Java
Scala
1.2.9
1.15–1.18
2.1 and later
8
2.11, 2.12
1.2.8
1.13–1.17
2.1 and later
8
2.11, 2.12
1.2.7
1.11–1.15
2.1 and later
8
2.11, 2.12
Configuration
This section describes StarRocks parameter settings and data type mapping. For more information, see Continuously load data from Apache Flink® | StarRocks.
Parameter description
|
Parameter |
Required |
Default value |
Description |
|
|
Yes |
NONE |
Specifies the connector as StarRocks. Set this parameter to |
|
|
Yes |
NONE |
Used to execute queries in StarRocks. Example: jdbc:mysql://fe-c-9b354c83e891**-internal.starrocks.aliyuncs.com:9030. Here, Note For information about how to obtain the private network address of the FE node in your EMR Serverless StarRocks instance, see View instance list and details. |
|
|
Yes |
NONE |
Specifies the private network address and HTTP port of the FE node in the format Example: fe-c-9b354c83e891****-internal.starrocks.aliyuncs.com:8030. |
|
|
Yes |
NONE |
Name of the StarRocks database. |
|
|
Yes |
NONE |
Name of the StarRocks table. |
|
|
Yes |
NONE |
Username for your StarRocks instance. For example, the default username is admin. To use the Flink Connector to import data into StarRocks, you need SELECT and INSERT permissions on the target table. If your user account lacks these permissions, grant them first. For more information, see Manage users and data authorization. |
|
|
Yes |
NONE |
Password for your StarRocks instance. |
|
|
No |
at-least-once |
Defines the semantic guarantee level of the sink to ensure reliability and consistency when writing data to the target system. Valid values:
|
|
|
No |
AUTO |
Specifies the data import interface. This parameter is supported starting from Flink Connector 1.2.4.
|
|
|
No |
NONE |
Specifies the prefix for Stream Load labels. If you use Flink Connector 1.2.8 or later and require exactly-once semantics, we recommend configuring a label prefix. |
|
|
No |
94371840 (90 MB) |
Maximum size of data buffered in memory before it is imported into StarRocks via Stream Load in one batch. A larger value improves import performance but may increase import latency. Valid range: [64 MB, 10 GB]. Note
|
|
sink.buffer-flush.max-rows |
No |
500000 |
Maximum number of rows buffered in memory before they are imported into StarRocks via Stream Load in one batch. Valid range: [64000, 5000000]. Note
This parameter takes effect only when |
|
sink.buffer-flush.interval-ms |
No |
300000 |
Interval (in milliseconds) for sending data, which controls the latency of writing data to StarRocks. Valid range: [1000, 3600000]. Note
This parameter takes effect only when |
|
sink.max-retries |
No |
3 |
Maximum number of retries after a Stream Load failure. If this limit is exceeded, the data import task fails. Valid range: [0, 10]. Note
This parameter takes effect only when |
|
sink.connect.timeout-ms |
No |
30000 |
Timeout (in milliseconds) for establishing an HTTP connection with the FE node. Valid range: [100, 60000]. In Flink Connector versions earlier than 1.2.9, the default value is |
|
sink.socket.timeout-ms |
No |
-1 |
Supported starting from Flink Connector 1.2.10. Timeout (in milliseconds) for the HTTP client to wait for data. The default value |
|
sink.wait-for-continue.timeout-ms |
No |
10000 |
Supported starting from Flink Connector 1.2.7. Timeout (in milliseconds) for waiting for the FE HTTP 100-continue response. Valid range: [3000, 60000]. |
|
sink.ignore.update-before |
No |
TRUE |
Supported starting from Flink Connector 1.2.8. When importing data into a primary key table, specifies whether to ignore UPDATE_BEFORE records from Flink. If set to false, such records are treated as DELETE operations in the primary key table. |
|
sink.parallelism |
No |
NONE |
Parallelism for writes. Applies only to Flink SQL. If not set, the Flink planner determines the parallelism. In multi-parallelism scenarios, ensure data is written in the correct order. |
|
sink.properties.* |
No |
NONE |
Parameters for Stream Load that control import behavior. |
|
sink.properties.format |
No |
csv |
Data format for Stream Load imports. The Flink Connector converts in-memory data to the specified format before importing it into StarRocks via Stream Load. Valid values: CSV or JSON. |
|
sink.properties.column_separator |
No |
\t |
Column delimiter for CSV data. |
|
sink.properties.row_delimiter |
No |
\n |
Row delimiter for CSV data. |
|
sink.properties.max_filter_ratio |
No |
0 |
Maximum error tolerance ratio for the import job. This is the maximum proportion of data rows that can be filtered out due to poor data quality. Valid range: 0–1. |
|
sink.properties.partial_update |
No |
false |
Specifies whether to enable partial updates. Valid values: |
|
sink.properties.partial_update_mode |
No |
row |
Specifies the partial update mode. Valid values:
|
|
sink.properties.strict_mode |
No |
false |
Specifies whether to enable strict mode for Stream Load. Strict mode affects import behavior when invalid rows (such as those with inconsistent column values) are encountered. Valid values: |
|
sink.properties.compression |
No |
NONE |
Supported starting from Flink Connector 1.2.10. Specifies the compression algorithm for Stream Load. Currently, only JSON format supports compression. Valid value: Note
Only StarRocks 3.2.7 and later support JSON compression. |
Data type mapping
|
Flink data type |
StarRocks data type |
|
BOOLEAN |
BOOLEAN |
|
TINYINT |
TINYINT |
|
SMALLINT |
SMALLINT |
|
INTEGER |
INTEGER |
|
BIGINT |
BIGINT |
|
FLOAT |
FLOAT |
|
DOUBLE |
DOUBLE |
|
DECIMAL |
DECIMAL |
|
BINARY |
INT |
|
CHAR |
STRING |
|
VARCHAR |
STRING |
|
STRING |
STRING |
|
DATE |
DATE |
|
TIMESTAMP_WITHOUT_TIME_ZONE(N) |
DATETIME |
|
TIMESTAMP_WITH_LOCAL_TIME_ZONE(N) |
DATETIME |
|
ARRAY<T> |
ARRAY<T> |
|
MAP<KT,VT> |
JSON STRING |
|
ROW<arg T...> |
JSON STRING |
Preparations
Obtain the Flink Connector JAR and upload it to your Flink cluster
-
You can obtain the Flink Connector JAR file using one of the following methods.
Method 1: Direct download
You can download different versions of the Flink Connector JAR file from the Maven Central Repository.
Method 2: Maven dependency
Add the Flink Connector as a dependency to the
pom.xmlfile of your Maven project in the following format.-
For Flink Connectors compatible with Flink 1.15 and later:
<dependency> <groupId>com.starrocks</groupId> <artifactId>flink-connector-starrocks</artifactId> <version>${connector_version}_flink-${flink_version}</version> </dependency> -
For Flink Connectors compatible with Flink versions earlier than 1.15:
<dependency> <groupId>com.starrocks</groupId> <artifactId>flink-connector-starrocks</artifactId> <version>${connector_version}_flink-${flink_version}_${scala_version}</version> </dependency>
Method 3: Manual compilation
-
Download the Flink Connector source code.
-
Run the following command to compile the Flink Connector source code into a JAR file.
sh build.sh <flink_version>For example, if your Flink version is 1.17, run the following command.
sh build.sh 1.17 -
After compilation, you can find the generated JAR file in the
target/directory.For example, the filename is typically in the format
flink-connector-starrocks-1.2.7_flink-1.17-SNAPSHOT.jar.NoteUnreleased Flink Connector versions include the
SNAPSHOTsuffix.
The Flink Connector JAR filename follows these formats:
-
For Flink 1.15 and later:
flink-connector-starrocks-${connector_version}_flink-${flink_version}.jar. For example, if you use Flink 1.17 and Flink Connector 1.2.8, the filename isflink-connector-starrocks-1.2.8_flink-1.17.jar. -
For Flink versions earlier than 1.15:
flink-connector-starrocks-${connector_version}_flink-${flink_version}_${scala_version}.jar. For example, if you use Flink 1.14, Scala 2.12, and Flink Connector 1.2.7, the filename isflink-connector-starrocks-1.2.7_flink-1.14_2.12.jar.NoteReplace the following placeholders as needed:
-
flink_version: Your Flink version number. -
scala_version: Your Scala version number. -
connector_version: Your Flink Connector version number.
-
-
-
Upload the Flink Connector JAR file that you obtained to the
flink-{flink_version}/libdirectory of your Flink cluster.For example, if you use an EMR cluster of version EMR-5.19.0, place the JAR file in the
/opt/apps/FLINK/flink-current/libdirectory.
Start the Flink cluster
-
Log on to the master node of your Flink cluster. For more information, see Log on to a cluster.
-
Run the following command to start the Flink cluster.
/opt/apps/FLINK/flink-current/bin/start-cluster.sh
Examples
Write data using Flink SQL
-
Create a database named
testin StarRocks, and then create a primary key table namedscore_boardin the database.CREATE DATABASE test; CREATE TABLE test.score_board( id int(11) NOT NULL COMMENT "", name varchar(65533) NULL DEFAULT "" COMMENT "", score int(11) NOT NULL DEFAULT "0" COMMENT "" ) ENGINE=OLAP PRIMARY KEY(id) DISTRIBUTED BY HASH(id); -
Log on to the master node of your Flink cluster. For more information, see Log on to a cluster.
-
Run the following command to start Flink SQL.
/opt/apps/FLINK/flink-current/bin/sql-client.sh -
Run the following command to create a table named
score_boardand insert data into it.CREATE TABLE `score_board` ( `id` INT, `name` STRING, `score` INT, PRIMARY KEY (id) NOT ENFORCED ) WITH ( 'connector' = 'starrocks', 'jdbc-url' = 'jdbc:mysql://<fe-{srClusterId}-internal.starrocks.aliyuncs.com>:9030', 'load-url' = '<fe-{srClusterId}-internal.starrocks.aliyuncs.com>:8030', 'database-name' = 'test', 'table-name' = 'score_board', 'username' = 'admin', 'password' = '<password>', ); INSERT INTO `score_board` VALUES (1, 'starrocks', 100), (2, 'flink', 100);If you are importing data into a StarRocks primary key table, you must explicitly specify the primary key in the Flink table DDL. For other types of StarRocks tables, such as Duplicate Key tables, specifying a primary key is optional.
Write data using Flink DataStream
Write a Flink DataStream job based on the type of input records.
-
Write CSV-formatted string data
If your input records are CSV-formatted strings, see the complete Flink DataStream job code in LoadCsvRecords.
/** * Generate CSV-format records. Each record has three values separated by "\t". * These values will be loaded to the columns `id`, `name`, and `score` in the StarRocks table. */ String[] records = new String[]{ "1\tstarrocks-csv\t100", "2\tflink-csv\t100" }; DataStream<String> source = env.fromElements(records); /** * Configure the Flink connector with the required properties. * You also need to add properties "sink.properties.format" and "sink.properties.column_separator" * to tell the Flink connector the input records are CSV-format, and the column separator is "\t". * You can also use other column separators in the CSV-format records, * but remember to modify the "sink.properties.column_separator" correspondingly. */ StarRocksSinkOptions options = StarRocksSinkOptions.builder() .withProperty("jdbc-url", jdbcUrl) .withProperty("load-url", loadUrl) .withProperty("database-name", "test") .withProperty("table-name", "score_board") .withProperty("username", "root") .withProperty("password", "") .withProperty("sink.properties.format", "csv") .withProperty("sink.properties.column_separator", "\t") .build(); // Create the sink with the options. SinkFunction<String> starRockSink = StarRocksSink.sink(options); source.addSink(starRockSink); -
Write JSON-formatted string data
If your input records are JSON-formatted strings, see the complete Flink DataStream job code in LoadJsonRecords.
/** * Generate JSON-format records. * Each record has three key-value pairs corresponding to the columns id, name, and score in the StarRocks table. */ String[] records = new String[]{ "{\"id\":1, \"name\":\"starrocks-json\", \"score\":100}", "{\"id\":2, \"name\":\"flink-json\", \"score\":100}", }; DataStream<String> source = env.fromElements(records); /** * Configure the Flink connector with the required properties. * You also need to add properties "sink.properties.format" and "sink.properties.strip_outer_array" * to tell the Flink connector the input records are JSON-format and to strip the outermost array structure. */ StarRocksSinkOptions options = StarRocksSinkOptions.builder() .withProperty("jdbc-url", jdbcUrl) .withProperty("load-url", loadUrl) .withProperty("database-name", "test") .withProperty("table-name", "score_board") .withProperty("username", "root") .withProperty("password", "") .withProperty("sink.properties.format", "json") .withProperty("sink.properties.strip_outer_array", "true") .build(); // Create the sink with the options. SinkFunction<String> starRockSink = StarRocksSink.sink(options); source.addSink(starRockSink); -
Write custom Java object data
If your input records are custom Java objects, see the complete Flink DataStream job code in LoadCustomJavaRecords.
-
In this example, a simple POJO class
RowDatais defined to represent each record.public static class RowData { public int id; public String name; public int score; public RowData() {} public RowData(int id, String name, int score) { this.id = id; this.name = name; this.score = score; } } -
The main code is as follows.
// Generate records which use RowData as the container. RowData[] records = new RowData[]{ new RowData(1, "starrocks-rowdata", 100), new RowData(2, "flink-rowdata", 100), }; DataStream<RowData> source = env.fromElements(records); // Configure the Flink connector with the required properties. StarRocksSinkOptions options = StarRocksSinkOptions.builder() .withProperty("jdbc-url", jdbcUrl) .withProperty("load-url", loadUrl) .withProperty("database-name", "test") .withProperty("table-name", "score_board") .withProperty("username", "root") .withProperty("password", "") .build(); /** * The Flink connector will use a Java object array (Object[]) to represent a row to be loaded into the StarRocks table, * and each element is the value for a column. * You need to define the schema of the Object[] which matches that of the StarRocks table. */ TableSchema schema = TableSchema.builder() .field("id", DataTypes.INT().notNull()) .field("name", DataTypes.STRING()) .field("score", DataTypes.INT()) // When the StarRocks table is a Primary Key table, you must specify notNull(), for example, DataTypes.INT().notNull(), for the primary key `id`. .primaryKey("id") .build(); // Transform the RowData to the Object[] according to the schema. RowDataTransformer transformer = new RowDataTransformer(); // Create the sink with the schema, options, and transformer. SinkFunction<RowData> starRockSink = StarRocksSink.sink(schema, options, transformer); source.addSink(starRockSink);The
RowDataTransformeris defined as follows.private static class RowDataTransformer implements StarRocksSinkRowBuilder<RowData> { /** * Set each element of the object array according to the input RowData. * The schema of the array matches that of the StarRocks table. */ @Override public void accept(Object[] internalRow, RowData rowData) { internalRow[0] = rowData.id; internalRow[1] = rowData.name; internalRow[2] = rowData.score; // When the StarRocks table is a Primary Key table, you need to set the last element to indicate whether the data loading is an UPSERT or DELETE operation. internalRow[internalRow.length - 1] = StarRocksSinkOP.UPSERT.ordinal(); } }
-
Synchronize data using Flink CDC 3.0
The Flink CDC 3.0 framework simplifies building streaming ELT pipelines from CDC data sources, such as MySQL or Kafka, to StarRocks. With this pipeline, you can:
-
Automatically create databases and tables
-
Synchronize full and incremental data
-
Synchronize schema changes
Starting from StarRocks Flink Connector v1.2.9, the connector is integrated into the Flink CDC 3.0 framework and renamed StarRocks Pipeline Connector. This connector supports all the preceding features. We recommend that you use it with StarRocks v3.2.1 or later to leverage the `fast_schema_evolution` feature, which further accelerates column additions and deletions and reduces resource consumption.
Best practices
Import into a primary key table
-
Create a database named
testin StarRocks, and then create a primary key table namedscore_board.CREATE DATABASE `test`; CREATE TABLE `test`.`score_board` ( `id` int(11) NOT NULL COMMENT "", `name` varchar(65533) NULL DEFAULT "" COMMENT "", `score` int(11) NOT NULL DEFAULT "0" COMMENT "" ) ENGINE=OLAP PRIMARY KEY(`id`) COMMENT "OLAP" DISTRIBUTED BY HASH(`id`); -
Insert data into the StarRocks table.
INSERT INTO `test`.`score_board` VALUES (1, 'starrocks', 100), (2, 'flink', 100); -
Run the following command to start the Flink SQL client.
/opt/apps/FLINK/flink-current/bin/sql-client.sh -
Update data.
Partial update
Partial update lets you update only specific columns, such as
name, without affecting others, such asscore.-
Create the
score_boardtable in the Flink SQL client and enable partial updates.CREATE TABLE `score_board` ( `id` INT, `name` STRING, PRIMARY KEY (id) NOT ENFORCED ) WITH ( 'connector' = 'starrocks', 'jdbc-url' = 'jdbc:mysql://<fe-{srClusterId}-internal.starrocks.aliyuncs.com>:9030', 'load-url' = '<fe-{srClusterId}-internal.starrocks.aliyuncs.com>:8030', 'database-name' = 'test', 'table-name' = 'score_board', 'username' = 'admin', 'password' = '<password>', 'sink.properties.partial_update' = 'true', -- only for Flink connector version <= 1.2.7 'sink.properties.columns' = 'id,name,__op' );-
sink.properties.partial_update: Enables partial updates. -
sink.properties.columns: Specifies the columns to update. If the Flink Connector version is 1.2.7 or earlier, you must also set thesink.properties.columnsoption toid,name,__opto inform the Flink connector which columns to update. Note that you must append the__opfield at the end. The__opfield indicates whether the import is an UPSERT or DELETE operation, and its value is automatically set by the Flink connector.
-
-
Insert updated data.
Insert two rows that have the same primary keys as existing data but with modified values in the
namecolumn.INSERT INTO score_board VALUES (1, 'starrocks-update'), (2, 'flink-update'); -
Query the StarRocks table in the SQL Editor.
SELECT * FROM `test`.`score_board`;You will see that only the values in the
namecolumn have changed, while thescorecolumn remains unchanged.The query returns two records:
id=1, name=starrocks-update, score=100andid=2, name=flink-update, score=100.
Conditional update
This example shows how to perform conditional updates based on the value of the
scorecolumn. A row is updated only if thescorevalue in the incoming data is greater than or equal to the current value in the StarRocks table.-
Create the
score_boardtable in the Flink SQL client as follows.CREATE TABLE `score_board` ( `id` INT, `name` STRING, `score` INT, PRIMARY KEY (id) NOT ENFORCED ) WITH ( 'connector' = 'starrocks', 'jdbc-url' = 'jdbc:mysql://<fe-{srClusterId}-internal.starrocks.aliyuncs.com>:9030', 'load-url' = '<fe-{srClusterId}-internal.starrocks.aliyuncs.com>:8030', 'database-name' = 'test', 'table-name' = 'score_board', 'username' = 'admin', 'password' = '<password>', 'sink.properties.merge_condition' = 'score', 'sink.version' = 'V1' );-
sink.properties.merge_condition: Set toscore. This specifies that the Flink Connector uses thescorecolumn as the update condition during data writes. -
sink.version: Set toV1. This specifies that the Flink Connector uses the Stream Load interface to import data.
-
-
Insert two rows of data into the table in the Flink SQL client.
The rows have the same primary keys as existing rows in the StarRocks table. The first row has a smaller
scorevalue, and the second row has a largerscorevalue.INSERT INTO `score_board` VALUES (1, 'starrocks-update', 99), (2, 'flink-update', 101); -
Query the StarRocks table in the SQL Editor.
SELECT * FROM `test`.`score_board`;You will see that only the second row has changed, while the first row remains unchanged.
The query returns two records: the first row
id=1, name=starrocks, score=100(unchanged) and the second rowid=2, name=flink-update, score=101(updated).
-
Import into a Bitmap column
The Bitmap data type is commonly used to accelerate exact distinct count scenarios, such as calculating unique visitors (UV). The following example shows how to import data into a Bitmap column of a StarRocks table using Flink SQL and query the UV count in StarRocks.
-
Create a StarRocks aggregate table in the SQL Editor.
Create an aggregate table named
page_uvin thetestdatabase with the following specifications:-
The
visit_userscolumn is defined as the BITMAP type and configured with the `BITMAP_UNION` aggregate function. -
page_idandvisit_dateserve as aggregate keys (AGGREGATE KEY) for grouping and deduplication.
CREATE TABLE `test`.`page_uv` ( `page_id` INT NOT NULL COMMENT 'page ID', `visit_date` datetime NOT NULL COMMENT 'access time', `visit_users` BITMAP BITMAP_UNION NOT NULL COMMENT 'user ID' ) ENGINE=OLAP AGGREGATE KEY(`page_id`, `visit_date`) DISTRIBUTED BY HASH(`page_id`); -
-
Create a table in the Flink SQL client.
Because Flink does not support the Bitmap type, you must implement column mapping and type conversion as follows:
-
In the Flink table, define the
visit_user_idcolumn as BIGINT to represent thevisit_userscolumn in the StarRocks table. -
Use the
sink.properties.columnsconfiguration to convert the data in thevisit_user_idcolumn to the Bitmap type using the `to_bitmap` function.
CREATE TABLE `page_uv` ( `page_id` INT, `visit_date` TIMESTAMP, `visit_user_id` BIGINT ) WITH ( 'connector' = 'starrocks', 'jdbc-url' = 'jdbc:mysql://<fe-{srClusterId}-internal.starrocks.aliyuncs.com>:9030', 'load-url' = '<fe-{srClusterId}-internal.starrocks.aliyuncs.com>:8030', 'database-name' = 'test', 'table-name' = 'page_uv', 'username' = 'admin', 'password' = '<password>', 'sink.properties.columns' = 'page_id,visit_date,visit_user_id,visit_users=to_bitmap(visit_user_id)' ); -
-
Insert data in the Flink SQL client.
Insert multiple rows into the
page_uvtable to simulate different users accessing pages at different times.visit_user_idis of the BIGINT type. Flink automatically converts it to the Bitmap type.INSERT INTO `page_uv` VALUES (1, CAST('2020-06-23 01:30:30' AS TIMESTAMP), 13), (1, CAST('2020-06-23 01:30:30' AS TIMESTAMP), 23), (1, CAST('2020-06-23 01:30:30' AS TIMESTAMP), 33), (1, CAST('2020-06-23 02:30:30' AS TIMESTAMP), 13), (2, CAST('2020-06-23 01:30:30' AS TIMESTAMP), 23); -
Query the UV count in the SQL Editor.
Use the aggregation capability of StarRocks to calculate the unique visitor count (UV) per page with
COUNT(DISTINCT visit_users).SELECT page_id, COUNT(DISTINCT visit_users) FROM page_uv GROUP BY page_id;For
page_id2,count(DISTINCT visit_users)is 1. Forpage_id1,count(DISTINCT visit_users)is 3.
Import into an HLL column
HyperLogLog (HLL) is a data type used for approximate distinct counting and is suitable for calculating unique visitors (UV) in large-scale data scenarios. The following example shows how to import data into an HLL column of a StarRocks table using Flink SQL and query the UV count in StarRocks.
-
Create a StarRocks aggregate table in the SQL Editor.
Create an aggregate table named
hll_uvin thetestdatabase with the following specifications:-
The
visit_userscolumn is defined as the HLL type and configured with the `HLL_UNION` aggregate function. -
page_idandvisit_dateserve as aggregate keys (AGGREGATE KEY) for grouping and deduplication.
CREATE TABLE `test`.`hll_uv` ( `page_id` INT NOT NULL COMMENT 'page ID', `visit_date` DATETIME NOT NULL COMMENT 'access time', `visit_users` HLL HLL_UNION NOT NULL COMMENT 'user ID' ) ENGINE=OLAP AGGREGATE KEY(`page_id`, `visit_date`) DISTRIBUTED BY HASH(`page_id`); -
-
Create a table in the Flink SQL client.
Because Flink does not support the HLL type, you must implement column mapping and type conversion as follows:
-
In the Flink table, define the
visit_user_idcolumn as BIGINT to represent thevisit_userscolumn in the StarRocks table. -
Use the
sink.properties.columnsconfiguration to map columns and convert the BIGINT-typevisit_user_iddata to the HLL type using the `hll_hash` function.
CREATE TABLE `hll_uv` ( `page_id` INT, `visit_date` TIMESTAMP, `visit_user_id` BIGINT ) WITH ( 'connector' = 'starrocks', 'jdbc-url' = 'jdbc:mysql://<fe-{srClusterId}-internal.starrocks.aliyuncs.com>:9030', 'load-url' = '<fe-{srClusterId}-internal.starrocks.aliyuncs.com>:8030', 'database-name' = 'test', 'table-name' = 'hll_uv', 'username' = 'admin', 'password' = '<password>', 'sink.properties.columns' = 'page_id,visit_date,visit_user_id,visit_users=hll_hash(visit_user_id)' ); -
-
Insert data in the Flink SQL client.
Insert multiple rows into the
hll_uvtable to simulate different users accessing pages at different times.visit_user_idis of the BIGINT type. Flink automatically converts it to the HLL type.INSERT INTO `hll_uv` VALUES (3, CAST('2023-07-24 12:00:00' AS TIMESTAMP), 78), (4, CAST('2023-07-24 13:20:10' AS TIMESTAMP), 2), (3, CAST('2023-07-24 12:30:00' AS TIMESTAMP), 674); -
Query the UV count in the SQL Editor.
Use the aggregation capability of StarRocks to calculate the unique visitor count (UV) per page with
COUNT(DISTINCT visit_users).SELECT `page_id`, COUNT(DISTINCT `visit_users`) FROM `hll_uv` GROUP BY `page_id`;The result is as follows.
page_id count(DISTINCT visit_users) 0 4 1 1 3 2