l
@Rocky hello
r
Hello! I'm Rocky, your StarRocks assistant. How can I help you today?
l
@Rocky delete FROM dmapp.DTM_LOG_SCORE WHERE SYS_RUN_DATE >= DATE '2026-06-07' AND SYS_RUN_DATE <= DATE '2026-07-05'; correct?
r
The syntax for your
DELETE
statement is generally correct, but its success depends on the table engine (data model) of
dmapp.DTM_LOG_SCORE
and whether
SYS_RUN_DATE
is a key column. 1. Data Model Requirements * Duplicate Key tables: You can use any column in the
WHERE
clause. * Primary Key tables: You can use any column in the
WHERE
clause. * Aggregate or Unique Key tables: You can only use key columns in the
WHERE
clause. If
SYS_RUN_DATE
is a value (metric) column in these models, the command will fail. 2. Syntax Details * Literal format: For Duplicate/Aggregate/Unique tables, the right side of the comparison must be a constant value. While
DATE '2026-06-07'
is often accepted, it is safer to use a simple string literal
'2026-06-07'
to ensure it isn't interpreted as a function or expression. * Operators: StarRocks supports
=
,
>
,
<
,
>=
,
<=
, and
AND
in the
DELETE
statement. 3. Performance Note
DELETE
operations in StarRocks are not intended for high-frequency use. They mark rows as deleted and rely on background compaction to physically remove them. If you are deleting a large range of data frequently, consider: * DROP PARTITION: If the table is partitioned by
SYS_RUN_DATE
, dropping the partition is much faster and more efficient. * TRUNCATE TABLE: If you are clearing the entire table. Summary Recommendation: If
SYS_RUN_DATE
is a key column (or it's a Primary/Duplicate Key table), the following is the standard way to write it:
Copy code
sql
DELETE FROM dmapp.DTM_LOG_SCORE 
WHERE SYS_RUN_DATE >= '2026-06-07' AND SYS_RUN_DATE <= '2026-07-05';
-- To verify the table type and keys if you are unsure: SHOW CREATE TABLE dmapp.DTM_LOG_SCORE; ``` ## References - [faq/Sql_faq.md](https://docs.starrocks.io/docs/faq/Sql_faq) - [sql-reference/sql-statements/table_bucket_part_index/DELETE.md](https://docs.starrocks.io/docs/sql-reference/sql-statements/table_bucket_part_index/DELETE)
l
@Rocky [2026-09-11, 041732 UTC] {extract_dag_creator.py:222} INFO - 📄 Executing pre-extract SQL: delete from dmapp.DTM_LOG_SCORE where SYS_RUN_DATE >= date '07-06-2026' and SYS_RUN_DATE <= date '05-07-2026' [2026-09-11, 041732 UTC] {taskinstance.py:3313} ERROR - Task failed with exception Traceback (most recent call last): File "/home/airflow/.local/lib/python3.12/site-packages/airflow/models/taskinstance.py", line 768, in _execute_task *result = _execute_callable(context=context, *execute_callable_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/airflow/.local/lib/python3.12/site-packages/airflow/models/taskinstance.py", line 734, in _execute_callable return ExecutionCallableRunner( ^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/airflow/.local/lib/python3.12/site-packages/airflow/utils/operator_helpers.py", line 252, in run *return self.func(*args, *kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/airflow/.local/lib/python3.12/site-packages/airflow/models/baseoperator.py", line 424, in wrapper *return func(self, *args, *kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/airflow/.local/lib/python3.12/site-packages/airflow/operators/python.py", line 238, in execute return_value = self.execute_callable() ^^^^^^^^^^^^^^^^^^^^^^^ File "/home/airflow/.local/lib/python3.12/site-packages/airflow/operators/python.py", line 256, in execute_callable *return runner.run(*self.op_args, *self.op_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/airflow/.local/lib/python3.12/site-packages/airflow/utils/operator_helpers.py", line 252, in run *return self.func(*args, *kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/opt/airflow/dags/bags/dwh-dmapp-starrocks/airflow_dags/extract_framework/extract_dag_creator.py", line 223, in _extract_table_to_target cur.execute(sql) File "/home/airflow/.local/lib/python3.12/site-packages/MySQLdb/cursors.py", line 179, in execute res = self._query(mogrified_query) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/airflow/.local/lib/python3.12/site-packages/MySQLdb/cursors.py", line 330, in _query db.query(q) File "/home/airflow/.local/lib/python3.12/site-packages/MySQLdb/connections.py", line 280, in query _mysql.connection.query(self, query) MySQLdb.ProgrammingError: (1064, 'Getting syntax error from line 1, column 54 to line 1, column 59. Detail message: Invalid date literal 07-06-2026.') [2026-09-11, 041732 UTC] {taskinstance.py:907} DEBUG - Task Duration set to 5.647635
r
The error is caused by the date format used in your Airflow task. StarRocks requires date literals to be in the
YYYY-MM-DD
format. In your Airflow log, the SQL being executed is:
... SYS_RUN_DATE >= date '07-06-2026' ...
The value
'07-06-2026'
is not recognized as a valid date. To fix this, change the date format to
YYYY-MM-DD
. Corrected SQL
Copy code
sql
DELETE FROM dmapp.DTM_LOG_SCORE 
WHERE SYS_RUN_DATE >= '2026-06-07' 
  AND SYS_RUN_DATE <= '2026-07-05';
Why it failed 1. Format: StarRocks follows the ISO 8601 standard for date strings.
DD-MM-YYYY
or
MM-DD-YYYY
will trigger a
1064
syntax error. 2. Date Literal: While you can use
DATE '2026-06-07'
, simply using the string
'2026-06-07'
is often cleaner and avoids any ambiguity with function calls in some client drivers. Recommendation for Airflow If you are using Airflow macros (like
ds
), ensure they are formatted correctly. For example: * Use
{{ ds }}
which defaults to
YYYY-MM-DD
. * If you are passing manual dates, ensure they are specifically in
YYYY-MM-DD
format. References • sql-reference/data-types/date-types/DATE.md • faq/Sql_faq.md References • sql-reference/data-types/date-types/DATE.md • sql-reference/sql-functions/date-time-functions/to_tera_date.md • sql-reference/sql-functions/date-time-functions/date.md • sql-reference/sql-functions/date-time-functions/date_format.md • sql-reference/sql-functions/date-time-functions/year.md • faq/Sql_faq.md • sql-reference/sql-functions/date-time-functions/to_date.md • sql-reference/data-types/date-types/DATETIME.md
l
@Rocky
ID
varchar(255) NULL COMMENT "",
LOAN_AMOUNT_PROPOSED
decimal(28, 5) NULL COMMENT "",
TOTAL_LOAN_AMOUNT
decimal(28, 5) NULL COMMENT "",
CUSTOMER_MAIN_INCOME
decimal(28, 5) NULL COMMENT "" ) ENGINE=OLAP PRIMARY KEY(
ID
) DISTRIBUTED BY HASH(
ID
) BUCKETS 10 PROPERTIES ( "compression" = "LZ4", "enable_persistent_index" = "true", "fast_schema_evolution" = "true", "replicated_storage" = "true", "replication_num" = "1" ); bảng này phải đặt là primary key, nhưng muốn partition theo ID thì như nào? ID là số bigint tăng từ 0
r
Để thực hiện partition theo cột
ID
trong bảng Primary Key của StarRocks, bạn cần lưu ý quy tắc quan trọng: Cột tham gia vào Partition Key phải là một phần của Primary Key. Vì
ID
của bạn đã là Primary Key, điều này hoàn toàn hợp lệ. Dưới đây là cách chỉnh sửa câu lệnh CREATE TABLE của bạn để chia partition theo
ID
(kiểu
BIGINT
như bạn mô tả): 1. Cách chia Partition theo dải giá trị (Range Partition) Đây là cách phổ biến nhất khi ID là số tăng dần. Bạn cần xác định các khoảng giá trị (ví dụ: mỗi 1 triệu ID là 1 partition).
Copy code
sql
CREATE TABLE dmapp.DTM_LOG_SCORE (
  ID BIGINT NOT NULL COMMENT "", -- Đổi sang BIGINT theo mô tả của bạn
  LOAN_AMOUNT_PROPOSED decimal(28, 5) NULL COMMENT "",
  TOTAL_LOAN_AMOUNT decimal(28, 5) NULL COMMENT "",
  CUSTOMER_MAIN_INCOME decimal(28, 5) NULL COMMENT ""
) ENGINE=OLAP
PRIMARY KEY(`ID`)
-- Thêm phần PARTITION BY ở đây
PARTITION BY RANGE(`ID`) (
  PARTITION p1 VALUES LESS THAN ("1000000"),
  PARTITION p2 VALUES LESS THAN ("2000000"),
  PARTITION p3 VALUES LESS THAN ("3000000")
)
DISTRIBUTED BY HASH(`ID`) BUCKETS 10
PROPERTIES (
"compression" = "LZ4",
"enable_persistent_index" = "true",
"fast_schema_evolution" = "true",
"replicated_storage" = "true",
"replication_num" = "1"
);
2. Một số lưu ý quan trọng: * Kiểu dữ liệu: Trong đoạn mã bạn gửi,
ID
đang để là
varchar(255)
. Nếu thực tế nó là số tăng dần, bạn nên đổi sang
BIGINT
để tối ưu hiệu năng tính toán và lưu trữ. * Tự động tạo Partition: StarRocks hiện tại hỗ trợ tự động tạo partition cho kiểu Date/DateTime (Dynamic Partitioning). Đối với kiểu số
BIGINT
, bạn thường phải tạo thủ công bằng câu lệnh
ALTER TABLE dmapp.DTM_LOG_SCORE ADD PARTITION...
khi dữ liệu tăng lên, hoặc định nghĩa sẵn một loạt các dải giá trị. * Tại sao nên chia Partition theo ID? * Giúp loại bỏ (pruning) các partition không cần thiết khi query theo khoảng ID. * Dễ dàng xóa dữ liệu cũ theo từng cụm ID bằng lệnh
DROP PARTITION
. * Số lượng Buckets: Bạn đang để
BUCKETS 10
. Lưu ý rằng đây là số bucket trên mỗi partition. Nếu bạn có quá nhiều partition nhỏ, tổng số bucket sẽ rất lớn, gây áp lực cho việc quản lý metadata. Lời khuyên: Nếu
ID
này tăng theo thời gian (ví dụ: ID sinh ra từ Snowflake hoặc sequence), và mục đích chính của bạn là quản lý vòng đời dữ liệu (xóa dữ liệu cũ), bạn có thể cân nhắc thêm một cột ngày tháng (
created_at
) để partition theo thời gian sẽ hiệu quả hơn trong thực tế vận hành. Nếu hành. Nếu hành. Nếu không, cách làm trên với
RANGE(ID)
là hoàn toàn chính xác.
l
@Rocky một partition nên để kích thước khoảng bao nhiểu dòng hay bao nhiều GB?
r
Trong StarRocks, việc thiết lập kích thước partition và bucket (tablet) hợp lý là yếu tố then chốt để đạt hiệu năng tối ưu. Dưới đây là các con số "vàng" từ tài liệu kỹ thuật và kinh nghiệm thực tế: 1. Kích thước theo Dung lượng (GB) * Mỗi Partition: Nên giữ kích thước dưới 100 GB. Nếu một partition quá lớn, các thao tác quản lý (như backup, phục hồi, compaction) sẽ trở nên chậm chạp. * Mỗi Bucket (Tablet): Đây là đơn vị lưu trữ nhỏ nhất. Kích thước lý tưởng của một tablet (sau khi nén) là từ 100 MB đến 1 GB. _ _Dưới 100 MB:* Tạo ra quá nhiều file nhỏ, làm tăng tải cho FE (Front-end) trong việc quản lý metadata. _ _Trên 10 GB:* Được coi là "Red Flag" (mức nguy hiểm), gây khó khăn cho việc di chuyển dữ liệu giữa các node và quá trình compaction. 2. Kích thước theo Số dòng * Ngưỡng bắt đầu chia Partition: Nếu bảng của bạn có trên 50 triệu dòng, StarRocks khuyến nghị bắt buộc phải sử dụng Partition. * Với bảng nhỏ hơn (vài triệu dòng), bạn có thể không cần chia Partition mà chỉ cần tập trung vào số lượng Bucket. 3. Cách tính số lượng Bucket (Phân tán dữ liệu) Vì bạn đã chọn
DISTRIBUTED BY HASH(ID) BUCKETS 10
, hãy kiểm tra lại dựa trên công thức:
Số lượng Bucket = (Dung lượng dự kiến của 1 Partition) / (1 GB)
_ _Ví dụ:* Nếu mỗi Partition của bạn chứa khoảng 50 GB dữ liệu, bạn nên để khoảng 50 Buckets thay vì 10 như hiện tại. * Số lượng Bucket thông thường: Nên nằm trong khoảng từ 10 đến 120 buckets trên mỗi partition. 4. Các giới hạn cần tránh (Red Flags) * Tổng số tablet trên 1 BE: Không nên vượt quá 200.000 tablets trên mỗi node BE. * Số lượng Partition trên một bảng: Mặc dù giới hạn lý thuyết cao hơn, nhưng khuyến nghị thực tế là nên giữ dưới 4.096 partitions để FE hoạt động ổn định nhất. Tóm tắt lời khuyên cho bảng của bạn: Nếu
ID
tăng dần và bạn chia Partition theo `ID`: 1. Ước lượng xem 100 triệu dòng chiếm bao nhiêu GB. 2. Chia dải ID sao cho mỗi partition chứa khoảng 50-100 GB hoặc khoảng vài chục triệu dòng. 3. Điều chỉnh
BUCKETS
sao cho mỗi file dữ liệu bên trong đạt khoảng 500MB - 1GB. Ví dụ thực tế: Nếu bảng của bạn mỗi dòng trung bình 100 bytes, thì 1 tỷ dòng sẽ chiếm khoảng 100 GB. Bạn có thể chia thành 2 partition (mỗi cái 50 GB) và mỗi partition để khoảng 50-60 buckets. Tài liệu tham khảo • best_practices/partitioning.md • knowledge/usage/best-practice.md References • best_practices/partitioning.md • best_practices/query_tuning/schema_tuning.md • knowledge/usage/best-practice.md
l
@Rocky có nên convert bảng 40 triệu dòng, 5GB ở oracle sang parquet rồi load stream hàng ngày vào starrocks ko? tư vấn cách làm tối ưu, để hàng ngày kéo dữ liệu bảng này về SR
r
Với quy mô 40 triệu dòng và 5GB, đây được coi là một bảng nhỏ đối với StarRocks. Việc convert sang Parquet rồi mới load là một phương án khả thi nhưng có thể gây thêm bước trung gian không cần thiết nếu hệ thống của bạn cho phép kết nối trực tiếp. Dưới đây là tư vấn cách làm tối ưu nhất dựa trên kinh nghiệm thực tế: 1. Có nên qua trung gian Parquet không? * KHÔNG NÊN (nếu mạng giữa Oracle và StarRocks ổn định): Bạn nên dùng JDBC Catalog để kéo trực tiếp. Việc export ra Parquet rồi load lại sẽ làm tăng độ trễ và tốn tài nguyên lưu trữ trung gian. * NÊN (nếu): Oracle nằm ở zone khác, bảo mật gắt gao không cho kết nối trực tiếp, hoặc bạn muốn lưu trữ file Parquet làm bản backup trên Data Lake (S3/HDFS). ────────── 2. Giải pháp tối ưu: Sử dụng JDBC Catalog (Kéo trực tiếp) StarRocks hỗ trợ tính năng External Catalog, cho phép nó "nhìn" thấy các bảng trong Oracle như thể chúng nằm trong StarRocks. Cách làm: 1. Tạo Catalog: Kết nối StarRocks với Oracle qua driver JDBC. 2. Đổ dữ liệu: Sử dụng lệnh
INSERT INTO ... SELECT
. Câu lệnh mẫu:
Copy code
sql
-- Chạy một lần để tạo kết nối
CREATE EXTERNAL CATALOG oracle_db
PROPERTIES (
    "type" = "jdbc",
    "user" = "username",
    "password" = "password",
    "jdbc_uri" = "jdbc:oracle:thin:@//host:port/service_name",
    "driver_class" = "oracle.jdbc.OracleDriver",
    "driver_url" = "<https://repo1.maven.org/maven2/com/oracle/database/jdbc/ojdbc8/19.3.0.0/ojdbc8-19.3.0.0.jar>"
);

-- Kéo dữ liệu hàng ngày (Incremental Load)
INSERT INTO starrocks_db.dtm_log_score
SELECT * FROM oracle_db.schema.oracle_table
WHERE update_time >= '2026-09-11 00:00:00';
────────── 3. Chiến lược Load hàng ngày (Daily Load) Vì bảng của bạn có Primary Key (
ID
)
, bạn nên sử dụng mô hình Primary Key Table của StarRocks để xử lý dữ liệu hàng ngày. Kịch bản A: Load bù (Upsert) - Tối ưu nhất Nếu bảng ở Oracle có cột dấu vết như
update_at
hoặc
ID
tăng dần: * Chỉ kéo các dòng mới hoặc các dòng có sự thay đổi từ Oracle. * StarRocks sẽ tự động ghi đè (upsert) dựa trên
ID
nếu dòng đó đã tồn tại, hoặc thêm mới nếu chưa có. Kịch bản B: Full Refresh (Nếu không có cột dấu vết) Với 5GB, việc xóa đi nạp lại hàng ngày (Truncate & Load) mất khoảng 1-3 phút trong StarRocks. * Sử dụng lệnh:
TRUNCATE TABLE ...
sau đó
INSERT INTO ... SELECT
. ────────── 4. Nếu bạn vẫn muốn dùng Parquet (Data Pipeline chuyên nghiệp) Nếu công ty bạn yêu cầu dùng Parquet/S3/HDFS, hãy dùng Broker Load. Đây là cách load dữ liệu không đồng bộ (asynchronous) và hiệu năng cực cao. 1. Dùng một công cụ (DataX, Airflow, hoặc script Python) export Oracle ra Parquet. 2. Đẩy file Parquet lên S3/HDFS. 3. Gọi lệnh Broker Load:
Copy code
sql
LOAD LABEL dmapp.label_2026_09_11
(
    DATA INFILE("<s3://your-bucket/path/to/data.parquet>")
    INTO TABLE dtm_log_score
    FORMAT AS "parquet"
)
WITH BROKER s3_broker (...)
PROPERTIES ("timeout" = "3600");
Tổng kết lời khuyên: 1. Dùng Primary Key Table (như bạn đã thiết kế ở câu hỏi trước) để tận dụng tính năng Upsert. 2. Dùng JDBC Catalog để đơn giản hóa Pipeline, tránh tạo ra file trung gian. 3. Tần suất: Với 40 triệu dòng, bạn có thể load theo giờ (Hourly) hoặc theo ngày (Daily) đều rất nhẹ nhàng. 4. Airflow: Bạn có thể dùng Airflow để trigger lệnh
INSERT INTO ... SELECT
từ JDBC Catalog để quản lý lịch trình và log lỗi. References • data_source/catalog/jdbc_catalog.md • loading/InsertInto.md • loading/BrokerLoad.md • loading/Loading_intro.md
l
@Rocky vẫn muốn dùng Parquet (Data Pipeline chuyên nghiệp), hướng dẫn các bước thực hiện chi tiết
r
Để xây dựng một pipeline chuyên nghiệp chuyển dữ liệu từ Oracle sang Parquet rồi vào StarRocks, bạn nên thực hiện theo kiến trúc chuẩn: Oracle → [ETL Tool] → Object Storage (S3/MinIO/HDFS) → StarRocks (Broker Load). Dưới đây là các bước chi tiết: Bước 1: Trích xuất dữ liệu (Oracle → Parquet) Bạn cần một công cụ để đọc dữ liệu từ Oracle và ghi ra định dạng Parquet trên hệ thống lưu trữ tập trung. * Công cụ khuyến nghị: Apache SeaTunnel (rất mạnh trong hệ sinh thái StarRocks) hoặc Spark/DataX. * Cấu trúc lưu trữ: Nên chia thư mục theo ngày để dễ quản lý và load bù khi cần. _ Ví dụ:
<s3://my-bucket/oracle_data/dtm_log_score/YYYY-MM-DD/_.parquet>
Lưu ý: Khi export, hãy đảm bảo kiểu dữ liệu giữa Oracle và Parquet tương thích (ví dụ:
NUMBER
trong Oracle tương ứng với
DECIMAL
trong Parquet). Bước 2: Thiết lập kết nối tại StarRocks Trước khi load, bạn cần khai báo thông tin kết nối tới nơi chứa file Parquet (Credential).
Copy code
sql
-- Nếu dùng S3 hoặc MinIO, bạn có thể tạo một Resource để dùng nhiều lần
CREATE REPOSITORY s3_repo
WITH BROKER "s3_broker" -- Hoặc không cần broker nếu dùng cấu hình trực tiếp
PROPERTIES (
    "aws.s3.endpoint" = "<http://your-s3-endpoint>",
    "aws.s3.access_key" = "your-access-key",
    "aws.s3.secret_key" = "your-secret-key",
    "aws.s3.region" = "us-east-1"
);
Bước 3: Thực hiện Load dữ liệu (Broker Load) Đây là cách "chuyên nghiệp" nhất để đẩy file Parquet vào StarRocks vì nó chạy bất đồng bộ, có khả năng chịu lỗi cao và không làm nghẽn kết nối của client. Câu lệnh Load hàng ngày:
Copy code
sql
LOAD LABEL dmapp.load_dtm_log_score_2026_09_14  -- Label phải là duy nhất mỗi lần chạy
(
    DATA INFILE("<s3://my-bucket/oracle_data/dtm_log_score/2026-09-14/*.parquet>")
    INTO TABLE dtm_log_score
    FORMAT AS "parquet"
)
WITH BROKER "s3_broker" 
PROPERTIES (
    "timeout" = "3600",      -- Thời gian tối đa cho phép load
    "max_filter_ratio" = "0" -- 0: lỗi 1 dòng cũng fail job để đảm bảo chính xác dữ liệu
);
*Vì bảng của bạn là Primary Key, StarRocks sẽ tự động thực hiện cơ chế Upsert: Nếu thấy
ID
đã có thì cập nhật, nếu chưa có thì thêm mới.* Bước 4: Kiểm tra trạng thái Load Vì lệnh
LOAD
là bất đồng bộ (trả về ngay lập tức), bạn cần kiểm tra trạng thái:
Copy code
sql
SHOW LOAD WHERE LABEL = "load_dtm_log_score_2026_09_14";
Bước 5: Tự động hóa (Orchestration) Để pipeline chạy hàng ngày, bạn nên dùng Airflow hoặc DolphinScheduler: 1. Task 1 (Export): Gọi SeaTunnel/Spark để kéo dữ liệu từ Oracle và đẩy lên S3 dưới dạng Parquet. 2. Task 2 (StarRocks Load): Gọi lệnh SQL
LOAD LABEL ...
vào StarRocks. 3. Task 3 (Sensor): Chạy vòng lặp kiểm tra
SHOW LOAD
cho đến khi trạng thái là
FINISHED
. Tại sao cách này tối ưu cho 40 triệu dòng (5GB)? 1. Hiệu năng: StarRocks đọc Parquet cực nhanh nhờ cơ chế đọc cột (columnar), 5GB dữ liệu có thể load xong trong vòng vài chục giây đến 2 phút. 2. Độ tin cậy: Cơ chế
LABEL
giúp ngăn chặn việc nạp trùng dữ liệu nếu Task bị chạy lại (Retry). 3. Khả năng mở rộng: Nếu sau này bảng tăng lên 400 triệu dòng hoặc 50GB, bạn chỉ cần tăng số lượng file Parquet, StarRocks sẽ tự động dùng các node BE để quét song song. Mẹo nhỏ: Để tối ưu hơn nữa, khi export Parquet từ Oracle, hãy chia nhỏ thành các file khoảng 100MB - 200MB/file thay vì một file 5GB duy nhất. Điều này giúp StarRocks huy động nhiều luồng xử lý cùng lúc. References • loading/BrokerLoad.md • loading/Loading_intro.md • loading/Etl_in_starrocks.md • sql-reference/sql-statements/data-manipulation/LOAD.md
l
@Rocky lỗi này làm sao, đang import vào starrocks từ dbeaver
r
Bạn vui lòng chụp ảnh màn hình hoặc copy nội dung lỗi cụ thể gửi vào đây để mình hỗ trợ chính xác nhất nhé. Tuy nhiên, khi import dữ liệu từ DBeaver vào StarRocks, người dùng thường gặp 3 lỗi phổ biến sau đây. Bạn thử kiểm tra xem mình có đang rơi vào trường hợp nào không: 1. Lỗi: "Insert has filtered data in strict mode" * Dấu hiệu: Thông báo kèm một đường link
tracking_url
. * Nguyên nhân: Dữ liệu bạn đang nạp bị sai kiểu dữ liệu, quá độ dài cột (ví dụ: chuỗi dài hơn
VARCHAR
đã khai báo), hoặc cột có giá trị
NULL
nhưng bảng không cho phép. * Cách xử lý: * Mở link
tracking_url
trong trình duyệt để xem dòng nào, cột nào bị lỗi. * Tạm thời tắt chế độ kiểm tra nghiêm ngặt bằng lệnh:
SET enable_insert_strict = false;
(StarRocks sẽ bỏ qua các dòng lỗi và nạp các dòng đúng). 2. Lỗi: "execute timeout" hoặc "Transaction timeout" * Dấu hiệu: Đang chạy nửa chừng thì DBeaver báo mất kết nối hoặc timeout. * Nguyên nhân: Mặc định lệnh
INSERT
có thời gian chờ giới hạn. Nếu file bạn import qua DBeaver quá lớn (vài trăm MB trở lên), nó sẽ bị timeout. * Cách xử lý: * Tăng thời gian timeout cho session đó:
SET insert_timeout = 28800;
(đơn vị giây). * Nếu dữ liệu lớn (trên 1GB), không nên dùng tính năng Import của DBeaver mà nên dùng Broker Load hoặc Stream Load như mình đã tư vấn ở trên. 3. Lỗi: "Reach limit of connections" * Dấu hiệu: DBeaver báo lỗi không thể tạo thêm kết nối. * Nguyên nhân: DBeaver khi import thường mở nhiều luồng (parallel) vượt quá giới hạn kết nối của user StarRocks. * Cách xử lý: * Tăng giới hạn kết nối:
ALTER USER 'username' SET PROPERTIES ("max_user_connections" = "500");
* Hoặc trong phần cài đặt Import của DBeaver, chỉnh Parallelism (số luồng song song) về 1. 4. Lỗi: "Label already exists" * Nguyên nhân: Bạn vừa chạy lệnh import lỗi và bấm chạy lại ngay lập tức với cùng một nhãn (label). * Cách xử lý: Đợi khoảng 5-10 phút hoặc đổi tên Label (nếu bạn tự đặt label). Thông thường DBeaver tự tạo label ngẫu nhiên nên lỗi này ít gặp hơn. Mẹo nhỏ: Nếu bạn đang dùng tính năng "Import Data" (chuột phải vào bảng -> Import Data), hãy đảm bảo bạn đã chọn đúng Driver là MySQL (vì StarRocks tương thích với giao thức MySQL). Hãy gửi mã lỗi hoặc ảnh, mình sẽ giải thích chi tiết hơn! References • faq/loading/Insert_into_faq.md • loading/InsertInto.md • faq/loading/Flink_connector_faq.md
l
@Rocky SQL Error [5609] [22001]: Data truncation: Failed to load data into tablet 63159942, because of too many versions, current/limit: 1001/1000. You can reduce the loading job concurrency, or increase loading data batch size. If you are loading data with Routine Load, you can increase FE configs routine_load_task_consume_second and max_routine_load_batch_size,: be:10.0.27.71 Data truncation: Failed to load data into tablet 63159942, because of too many versions, current/limit: 1001/1000. You can reduce the loading job concurrency, or increase loading data batch size. If you are loading data with Routine Load, you can increase FE configs routine_load_task_consume_second and max_routine_load_batch_size,: be:10.0.27.71
r
Lỗi này xảy ra do bạn đang nạp dữ liệu vào StarRocks theo kiểu "mưa dầm" (quá nhiều lệnh
INSERT
nhỏ trong thời gian quá ngắn). Tại sao bị lỗi này? Mỗi khi bạn thực hiện một lệnh
INSERT
hoặc một lần commit dữ liệu, StarRocks sẽ tạo ra một version (rowset) mới cho các tablet. StarRocks có một cơ chế chạy ngầm gọi là Compaction để gộp các version nhỏ này thành version lớn hơn. * Giới hạn: Mặc định mỗi tablet chỉ cho phép tối đa 1000 versions. * Vấn đề: DBeaver khi import thường gửi dữ liệu theo từng batch nhỏ hoặc từng dòng một. Nếu tốc độ tạo version mới nhanh hơn tốc độ Compaction gộp lại, bạn sẽ chạm ngưỡng 1000 và bị từ chối nạp tiếp. ────────── Cách khắc phục ngay trong DBeaver Nếu bạn vẫn muốn dùng DBeaver để import, hãy điều chỉnh các thông số trong cửa sổ Import Data: 1. Tăng Batch Size (Commit count): Thay vì để mặc định (thường là 100 hoặc 1000), hãy tăng lên 10,000 hoặc 50,000. Điều này giúp giảm số lượng version được tạo ra. 2. Giảm Parallelism: Trong phần Data load settings, hãy để Max threads = 1. Việc chạy đa luồng từ DBeaver càng làm tăng tốc độ tạo version và gây lỗi nhanh hơn. ────────── Cách khắc phục triệt để (Khuyên dùng) Với bảng 40 triệu dòng (5GB), dùng DBeaver là cách kém tối ưu nhất vì nó rất chậm và dễ gây lỗi version như trên. Bạn nên dùng các cách sau: 1. Dùng Stream Load (Nếu có file CSV/Parquet cục bộ) Đây là cách nhanh nhất. Thay vì dùng DBeaver, bạn dùng lệnh
curl
để đẩy file trực tiếp vào StarRocks. Cách này chỉ tạo ra 1 version duy nhất cho toàn bộ file.
Copy code
bash
curl --location-trusted -u admin:password \
    -H "label:load_log_score_01" \
    -H "column_separator:," \
    -T your_data_file.csv \
    http://<FE_IP>:8030/api/test_db/dtm_log_score/_stream_load
2. Điều chỉnh cấu hình BE (Nếu bạn có quyền quản trị cluster) Nếu bạn bắt buộc phải nạp tần suất cao, bạn có thể cấu hình để StarRocks gộp version nhanh hơn. Sửa file
be.conf
của tất cả các BE:
Copy code
conf
# Tăng số luồng xử lý compaction
cumulative_compaction_num_threads_per_disk = 4
base_compaction_num_threads_per_disk = 2

# (Tùy chọn) Tăng giới hạn version lên nếu cần, nhưng không nên quá 2000
tablet_max_versions = 2000
Sau khi sửa cần restart BE. Tổng kết: Bạn đang gặp lỗi kinh điển của StarRocks khi dùng công cụ UI (như DBeaver/Navicat) để nạp dữ liệu lớn. Hãy tăng Batch Size trong DBeaver lên thật lớn, hoặc chuyển sang dùng Stream Load / Broker Load để nạp dữ liệu một cách chuyên nghiệp và hiệu quả chuyên nghiệp hơn. References • faq/loading/Loading_faq.md • administration/management/BE_configuration.md • loading/StreamLoad.md References • administration/management/BE_configuration.md • faq/loading/Loading_faq.md • faq/loading/Routine_load_faq.md
l
@Rocky sao mấy cột Date của Starrock, có constraint gì đặc biệt hơn à, phải đúng format String mới write xuống được. Datetime bình thường không write xuống được mà cũng nhờ vậy mà xử lý ngày tháng rất nhanh ạ
r
Đúng là StarRocks có vẻ "khắt khe" về định dạng ngày tháng khi nạp dữ liệu (Load), nhưng đây chính là "bí quyết" giúp nó đạt tốc độ xử lý cực nhanh mà bạn đã nhận thấy. Dưới đây là lý do tại sao nó lại như vậy: 1. "Vỏ bọc" là String nhưng "Lõi" là Nhị phân (Binary) Khi bạn nhìn vào StarRocks, bạn thấy định dạng
YYYY-MM-DD
. Nhưng thực tế, StarRocks không lưu dưới dạng String. * DATE: Được lưu dưới dạng số nguyên 4-byte. * DATETIME: Được lưu dưới dạng số nguyên 8-byte. * Tại sao phải đúng format? Khi bạn nạp dữ liệu (qua DBeaver hoặc lệnh LOAD), bộ giải mã (Parser) của StarRocks được tối ưu hóa cực mạnh để chuyển đổi chuỗi
YYYY-MM-DD
sang số nhị phân một cách nhanh nhất. Nếu đưa vào định dạng lạ (như
DD/MM/YYYY
), Parser sẽ không hiểu và báo lỗi để tránh việc phải đoán định dạng làm chậm hệ thống. 2. Tại sao xử lý ngày tháng trong StarRocks lại rất nhanh? Sở dĩ bạn thấy nó nhanh vượt trội là nhờ 3 yếu tố kỹ thuật: * Lưu trữ dạng Cột (Columnar Storage): Các giá trị ngày tháng của hàng triệu dòng được xếp liền kề nhau trong bộ nhớ. * Công cụ thực thi Vector hóa (Vectorized Execution): Thay vì xử lý từng dòng một, StarRocks dùng tập lệnh SIMD của CPU để xử lý một lúc hàng nghìn giá trị ngày tháng chỉ trong một nhịp xung nhịp. * Operation on Encoded Data: Với một số phép so sánh, StarRocks thậm chí có thể thực hiện trực tiếp trên dữ liệu đã mã hóa mà không cần giải nén hoàn toàn. 3. Cách xử lý nếu dữ liệu nguồn không đúng format Nếu bạn nạp từ Oracle/DBeaver mà cột ngày tháng bị lệch format (ví dụ:
2024/09/14
), bạn có 2 cách chuyên nghiệp: * Cách 1: Ép kiểu trong lệnh Load (Khuyên dùng) Nếu dùng lệnh
LOAD
, bạn có thể dùng hàm
STR_TO_DATE
để biến đổi ngay lúc nạp:
Copy code
sql
(col_date_temp, ...)
SET (
    real_date_column = STR_TO_DATE(col_date_temp, '%Y/%m/%d %H:%i:%s')
)
* Cách 2: Sử dụng SQL của StarRocks để cast Nếu bạn đã lỡ nạp vào một bảng tạm dưới dạng
VARCHAR
, hãy chuyển nó sang bảng chính:
Copy code
sql
INSERT INTO main_table (date_col)
SELECT CAST(date_string AS DATE) FROM staging_table;
Tóm lại: Việc ép format "đúng chuẩn" lúc đầu giống như việc bạn sắp xếp hàng hóa vào pallet đúng kích thước trước khi đưa vào kho tự động. Nó mất công lúc đầu một chút nhưng giúp "cỗ máy" StarRocks chạy với tốc độ tối đa khi truy vấn. References • sql-reference/data-types/date-types/DATETIME.md • introduction/Features.md • unloading/Spark_connector.md References • introduction/Features.md • release_notes/release-3.3.md • sql-reference/sql-functions/date-time-functions/date_trunc.md • administration/management/timezone.md