Synthetic Key trong Qlik (P1)

Mô hình lựa chọn liên kết (Associative Selection Model) là nền tảng tổ chức dữ liệu của các QlikView và Qlik Sense application. Sau khi load dữ liệu từ hệ thống nguồn, Qlik Sense tự động liên kết các bảng bằng cách tạo kết nối trên mỗi cặp field cùng tên ở 2 bảng. Tuy nhiên, nếu 2 bảng chứa nhiều hơn 1 field chung, một khóa tổng hợp (Synthetic Key) sẽ được hình thành giữa 2 bảng.

Có một niềm tin phổ biến trong cộng động Qlik developer là Synthetic Key làm chậm data model và gây ra các vấn đề sử dụng bộ nhớ không hiệu quả. Các tài liệu về thiết kế data model cũng thường khuyên nên tránh Synthetic Key trong data model nếu có thể.

Vậy quan niệm này có đúng hay không? Synthetic Key làm chậm data model như thế nào (nếu có)? Qlik Sense thực chất xử lý Synthetic Key như thế nào trong memory? Bài viết hôm nay của VietQlikies sẽ góp phần trả lời các câu hỏi trên.

Khái niệm Synthetic Key

Nếu từng làm việc với các hệ CSDL như Oracle hay MySQL, hẳn bạn rất quen thuộc với khái niệm composite key (khóa phức hợp). Composite key là một nhóm từ 2 cột trở lên trong 1 bảng dữ liệu có khả năng xác định duy nhất một dòng trong bảng đó. Composite key được sử dụng khi không có cột nào trong bảng có khả năng đại diện duy nhất cho 1 dòng dữ liệu.

Synthetic key là cách QlikView và Qlik Sense xử lý composite key trong data model. Synthetic key cũng được tạo thành từ nhiều field, nhưng không nhất thiết phải xác định duy nhất một dòng dữ liệu (vì bảng dữ liệu trong Qlik không dùng primary key và foreign key như database).

Qlik engine xử lý Synthetic Key như thế nào trong bộ nhớ?

Trong bài viết trước Qlik engine lưu trữ dữ liệu như thế nào? , chúng ta đã biết mỗi cột dữ liệu trong Qlik được lưu trữ thành một symbol table. Đối với các simple key (liên kết chỉ bao gồm 1 cột dữ liệu), symbol table không có gì khác so với các data field thông thường.

Tuy nhiên, với synthetic key thì lại khác: không có sẵn một symbol table chứa tất cả các tổ hợp giá trị có thể có của các cột dữ liệu thuộc synthetic key. Vì vậy, khi phát hiện 2 bảng dữ liệu có hơn 1 field cùng tên, Qlik engine phải tạo ra một bảng dữ liệu mới để lưu trữ synthetic key giữa 2 bảng. Trong bảng synthetic key, mỗi dòng chứa một tổ hợp giá trị của các key field, và một giá trị ID duy nhất cho tổ hợp đó. Trong 2 bảng ban đầu, các cột tạo thành synthetic key sẽ được thay thế bởi ID tương ứng.

Ví dụ, xét một hệ thống bán hàng có mã đơn hàng (OrderID) duy nhất cho mỗi đơn hàng. Tuy nhiên, OrderID lại được reset vào đầu mỗi ngày. Nếu mỗi ngày bán được 100 đơn hàng, OrderID được đánh số thứ tự từ 1 đến 100 và tương tự cho ngày hôm sau. Vì vậy, một đơn hàng được xác định duy nhất bởi tổ hợp 2 giá trị: OrderDate OrderID. Xét 2 bảng dữ liệu sau:

Orders:
LOAD * INLINE [
OrderDate, OrderID, SalesPerson
20190901, 1, John
20190901, 2, David 
20190901, 3, Susan  
20190902, 1, John 
20190902, 2, Susan  
20190903, 1, David 
];

OrderDetails:
LOAD * INLINE [
OrderDate, OrderID, Product, Price
20190901, 1, T-shirt, 100
20190901, 1, Jacket, 150 
20190901, 2, Polo, 80 
20190902, 1, Sneaker, 200
20190902, 1, Polo, 160
20190902, 2, Jacket, 70
]; 

Sau khi load 2 bảng trên, Qlik Sense nhận thấy 2 bảng có cùng 2 cột (OrderDate, OrderID) nên sẽ tự động dùng 2 cột này để tạo một synthetic key.

Mở data model viewer, ta thấy ngoài 2 bảng Orders OrderDetails, Qlik Sense tạo thêm bảng &Syn 1 Table để lưu trữ các giá trị của Synthetic Key. Bảng này chứa tất cả các tổ hợp giá trị (OrderDate, OrderID) đã xuất hiện ít nhất ở 1 trong 2 bảng Orders OrderDetails. Ngoài ra, ở 2 bảng ban đầu, 2 cột Orders OrderDetails được thay thế bằng cột &Syn 1, chứa ID của Synthetic Key tương ứng với mỗi dòng.

Synthetic Key có làm chậm data model không?

Để trả lời câu hỏi trên, trước hết ta cần chỉ ra cách thức tự xử lý composite key trong data ban đầu mà không dùng Synthetic Key mặc định của Qlik Sense. Từ đó ta có thể so sánh performance của 2 data model dùng và không dùng Synthetic Key.

Xử lý composite key theo cách thủ công

Cách làm thường thấy nhất là ghép (concatenate) giá trị của các field trong Synthetic Key lại, sau đó dùng hàm AutoNumber() để tạo ra key dạng numeric cho mỗi giá trị Synthetic Key. Hàm AutoNumber() tạo ra một số nguyên tăng dần cho mỗi giá trị duy nhất trong một field. Ví dụ, filed Char chứa 5 giá trị A, B, C, A, C. AutoNumber(Char) sẽ trả về 1, 2, 3, 1, 3 tương ứng.

Trong ví dụ trên, composite key trong 2 bảng Orders OrderDetails được xử lý với đoạn script sau để tránh việc Qlik Sense tự động tạo Synthetic Key:

Orders_WithKey:
LOAD 
     AutoNumber(OrderDate & '-' & OrderID) as OrderKey,
     OrderDate, OrderID, SalesPerson
Resident Orders;

OrderDetails_WithKey:
LOAD 
    AutoNumber(OrderDate & '-' & OrderID) as OrderKey,
     Product, Price
Resident OrderDetails;

DROP TABLES Orders, OrderDetails;

Sau khi tạo field OrderKey dùng làm khóa giữa 2 bảng, ta phải xóa 2 cột OrderDate, OrderID ở 1 trong 2 bảng để Qlik Sense không tự động tạo Synthetic Key mới (đoạn script trên xóa trong bảng OrderDetails). Sau khi reload và mở Data Model viewer, ta thấy 2 bảng được liên kết bởi field mới OrderKey. Bảng &Syn 1 Table đã không còn tồn tại trong data model.

So sánh với Synthetic Key

Như vậy cách làm này có tốt hơn Synthetic Key tự động của Qlik? Liên hệ bài viết trước Qlik engine lưu trữ dữ liệu như thế nào?, ta thấy với cách làm này Qlik Sense tạo một symbol table cho field OrderKey mới được tạo ra. Hay nói cách khác, chính là một symbol table chứa tất cả các tổ hợp giá trị của 2 cột (OrderDate, OrderID). Như vậy về mặt định nghĩa, symbol table này thật ra không khác gì bảng &Syn 1 Table do Qlik Sense tự động tạo ở trường hợp dùng Synthetic Key, và vì vậy performance không có gì tốt hơn Synthetic Key tự động do Qlik engine tạo ra.

Theo xác nhận của Henric Cronström (phó chủ tịch phụ trách công nghệ của Qlik) trong Qlik design blog, Synthetic Key là một giải pháp gọn nhẹ, chính xác và hiệu quả của Qlik engine để xử lý composite key. Synthetic Key không sử dụng nhiều bộ nhớ và CPU hơn cách tạo key thủ công bằng cách ghép chuỗi và hàm AutoNumber() nêu trên.

Trong cộng đồng Qlik Community, Synthetic Key có “xấu” hay không vẫn là một vấn đề gây tranh cãi. Tuy nhiên, đến nay chưa có test có hệ thống nào chỉ ra khác biệt rõ ràng về performance giữa 2 trường hợp: Synthetic Key tự động và tự xử lý composite key như trên.

Kết luận

Như vậy có thể tạm kết luận: nếu data ban đầu thực sự có chứa một vài composite key giữa một số bảng, Synthetic Key tự động của Qlik vẫn là một giải pháp tốt.

Vấn đề thực sự là khi có quá nhiều synthetic key trong một data model. Theo như khuyến cáo trên help site của Qlik:

Khi số lượng Synthetic Key tăng lên, tùy vào khối lượng dữ liệu, cấu trúc bảng và các yếu tố khác, Qlik Sense có thể không xử lý các Synthetic Key một cách hiệu quả, và có thể dẫn đến sử dụng quá nhiều thời gian và/ hoặc bộ nhớ. Trong trường hợp đó, bạn cần phải thiết kế lại script và cố gắng loại bỏ Synthetic Key

Trong thực tế, nếu data model của bạn chứa vài chục Synthetic Key trở lên, bạn có thể sẽ gặp lỗi -1 khi reload. Lỗi này thường gặp khi có vấn đề về bộ nhớ, và thường có dạng như sau trong script log:

2018-04-17 07:25:49      -1 = 
2018-04-17 07:25:54      Execution Failed
2018-04-17 07:25:54      Execution finished.​

Ở bài viết sau, VietQlikies sẽ trình bày tiếp các chủ đề vì sao nên tránh Synthetic Key và các cách loại bỏ Synthetic Key trong data model.

Bình luận về bài viết này