Fair2020 - paper - 13 - một Đề Xuất Cải Tiến Thuật Toán Join Đệ Qui Trên Tập Dữ Liệu Lớn

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 9

Kỷ yếu Hội nghị Quốc gia lần thứ XIII về Nghiên cứu cơ bản và ứng dụng Công Nghệ

thông tin (FAIR); Nha Trang, ngày 6-7/8/2020

MỘT ĐỀ XUẤT CẢI TIẾN THUẬT TOÁN JOIN ĐỆ QUI


TRÊN TẬP DỮ LIỆU LỚN
Triệu Thanh Ngoan 1, Phan Anh Cang2, Phan Thượng Cang 1
1
Khoa Công Nghệ Thông Tin và Truyền Thông, Đại học Cần Thơ
2
Khoa Công Nghệ Thông Tin, Đại học Sư Phạm Kỹ Thuật Vĩnh Long
ttngoan@cit.ctu.edu.vn, cangpa@vlute.edu.vn, ptcang@cit.ctu.edu.vn

TÓM TẮT— Với môi trường phát triển ngày càng nhiều của dữ liệu lớn, việc xử lý dữ liệu một cách nhanh chóng và hiệu quả
luôn luôn được sự quan tâm từ các nhà nghiên cứu. Trong việc tính toán dữ liệu lớn, hoạt động join là một hoạt động tính toán cơ
bản, xuất hiện trong rất nhiều câu truy vấn dữ liệu đặc biệt là join đệ qui. Hoạt động này thực hiện lặp lại nhiều lần hai công việc
tính toán bắc cầu và tính khác biệt. Các công việc này sẽ tạo ra nhiều dữ liệu trung gian và chuyển đổi chúng qua mạng. Có thể nói,
hoạt động join là một hoạt động tốn khá nhiều chi phí làm giảm hiệu suất cho các câu truy vấn dữ liệu lớn. Vì vậy, đề tài này tiến
hành thực hiện cải tiến giải thuật Semi-Naive cho join đệ qui trên tập dữ liệu lớn bằng cách sử dụng giải thuật join ba chiều và bộ lọc
trong môi trường MapReduce của Spark. Sự cải tiến này nhằm làm giảm số lần lặp, số công việc MapReduce cần thiết, và giảm dữ
liệu dư thừa. Thực nghiệm chỉ ra rằng nghiên cứu này đã cải tiến đáng kể hiệu suất thực thi câu truy vấn Join đệ qui trong môi trường
dữ liệu lớn.
Từ khóa— Big Data, Recursive Join, Optimize three-way join, Apache spark
I. GIỚI THIỆU
Mỗi người khi sử dụng Internet đều góp phần tạo ra khối lượng lớn dữ liệu mỗi ngày. Big data đã và đang là một
thuật ngữ thu hút được nhiều sự quan tâm từ các nhà nghiên cứu. Việc quản lý, lưu trữ, truy vấn và xử lý Big Data đã và
đang là một vấn đề được quan tâm nhằm sử dụng thông tin một cách hữu ích, tận dụng được giá trị của nguồn dữ liệu
đang có. Google đã thiết kế ra mô hình lập trình xử lý dữ liệu song song phân tán MapReduce để nhằm hỗ trợ giải quyết
các vấn đề liên quan đến dữ liệu lớn. Mô hình MapReduce đã trở thành một trong những nền tảng xử lý dữ liệu lớn phổ
biến hiện nay [1].
Một trong những hoạt động liên quan đến việc phân tích và truy xuất dữ liệu thường gặp đó là câu truy vấn join
giữa các tập dữ liệu lớn. Join là một hoạt động căn bản trong xử lý dữ liệu, nó kết nối nhiều quan hệ hay nhiều tập dữ
liệu có một số thuộc tính chung thành một quan hệ mới. Đặc biệt là Join đệ quy, đây là một hoạt động phức tạp với chi
phí lớn và không được hỗ trợ trực tiếp bởi mô hình MapReduce [2, 3, 10]. Tuy nhiên hoạt động này thường được dùng
trong các câu truy vấn, vì vậy cần có những nghiên cứu trong lĩnh vực này để cải tiến hiệu suất và thời gian xử lý cho
các câu truy vấn, nhất là trong ngữ cảnh môi trường dữ liệu lớn.
Có rất nhiều thuật toán được được biết đến để tính bao đóng bắc cầu cho một quan hệ trong cơ sở dữ liệu truyền
thống như Naive [4], Semi-Naive [4], Magic-set [5], hay Smart [2, 6]. Afrati et al. [7] nêu ra cách thực hiện đệ quy trên
cụm máy tính để tính toán bao đóng bắc cầu phi tuyến tính cho câu truy vấn đệ quy. Họ sử dụng hai nhóm tác vụ là tác
vụ join (Join tasks) và tác vụ loại bỏ trùng lắp (Dup-elim tasks). Tác vụ join sẽ thực hiện việc join các tuples và tác vụ
loại bỏ trùng lắp sẽ làm nhiệm vụ loại bỏ các tuples trùng lắp với tuples được tìm thấy trước đó trước khi chuyển nó đến
tác vụ join. Nghiên cứu còn thảo luận một số giải pháp thay thế để hỗ trợ phục hồi từ các lỗi mà không cần khởi động lại
toàn bộ công việc.
Shaw et al. [8] đã đề xuất tối ưu hoá giải thuật Semi-Naive cho câu truy vấn join đệ quy trong môi trường Hadoop
MapReduce. Trong Hadoop, việc thực hiện giải thuật join Semi-Naive cần có ba nhóm công việc MapReduce: một cho
việc thực hiện thao tác join các tuples (Join), một cho việc tính toán và xoá bỏ các bộ dữ liệu trùng lắp (Projection), và
một cho việc kết hợp kết quả với kết quả trước đó (Differrence). Nhóm tác giả chỉ ra rằng có thể không cần sử dụng công
việc MapReduce riêng cho việc Projection mà có thể kết hợp vào cho nhóm tác vụ Join và Difference. Tóm lại, giải pháp
thực hiện việc lặp hai công việc trên MapReduce là công việc join và công việc tính tập dữ liệu tăng cường. Sử dụng bộ
nhớ đệm để làm giảm thiểu chi phí liên quan. Tuy nhiên, chi phí đọc viết bộ nhớ đệm là đáng kể do cả bộ nhớ đệm phải
viết lại mỗi khi có tuples mới trong tập dữ liệu tăng cường được tìm thấy.
Một nghiên cứu gần đây nhất [9] đã đề xuất giải pháp tối ưu hoá join đệ quy trong môi trường Spark. Nhóm
nghiên cứu cải tiến join đệ qui với thuật toán Semi-Naive sử dụng cơ chế xử lý lặp trên bộ nhớ với sự hỗ trợ của Spark
RDD. Sử dụng cơ chế vùng đệm hỗ trợ bởi Spark để thực hiện cache tập dữ liệu cố định trên bộ nhớ nhằm giảm thiểu
chi phí đọc viết dữ liệu lại nhiều lần. Ngoài ra, nghiên cứu còn sử dụng bộ lọc giao Intersection Bloom Filter [3, 10, 11]
để loại bỏ dữ liệu dư thừa không tham gia vào hoạt động join làm giảm thiểu đáng kể chi phí liên quan.
Từ những nghiên cứu có liên quan trên, chúng ta có thể thấy được các nhóm nghiên cứu đã tận dụng cơ chế xử lý
lặp, cơ chế cache hoặc bộ lọc để có thể tối ưu hoá giải thuật Semi-Naive nguyên mẫu. Tuy nhiên những nghiên cứu này
chỉ tập trung vào việc lọc dữ liệu dư thừa hoặc ứng dụng những tiện ích của Spark để hỗ trợ cho join đệ quy mà không
cải tiến trực tiếp từ giải thuật.
2 MỘT ĐỀ XUẤT CẢI TIẾN THUẬT TOÁN JOIN ĐỆ QUI TRÊN TẬP DỮ LIỆU LỚN

Trong giải thuật Semi-Naive cho join đệ qui, tại mỗi lần lặp đều thực hiện thao tác join tập dữ liệu K và tập dữ
liệu này là không đổi. Như vậy, nếu chúng ta thực hiện thêm một lần thao tác join tập K trên cùng một lần lặp thì số lần
lặp của giải thuật sẽ giảm đi 2 lần. Việc đề xuất này sẽ được đánh giá thông qua thực nghiệm để thấy rõ trong trường hợp
nào, điều kiện nào thì việc cải tiến sẽ mang lại hiệu quả.
II. CƠ SỞ LÝ THUYẾT
A. Apache Hadoop và Apache Spark
Apache Hadoop là một tập hợp các tiện ích phần mềm nguồn mở, hỗ trợ sử dụng cụm gồm nhiều máy tính để giải quyết
các vấn đề liên quan đến lượng dữ liệu và tính toán khổng lồ. Nó cung cấp một khung phần mềm để lưu trữ phân tán và
xử lý dữ liệu lớn bằng mô hình lập trình MapReduce [17]. Cốt lõi của Apache Hadoop bao gồm bộ phận lưu trữ, được
gọi là Hệ thống tập phân tán Hadoop (HDFS) và một phần xử lý là mô hình lập trình MapReduce. HDFS được sử dụng
để lưu trữ dữ liệu và MapReduce được sử dụng để xử lý dữ liệu.
Apache Spark là một công cụ phân tích hợp nhất nhanh chóng cho dữ liệu lớn và máy học, ban đầu được phát triển tại
UC Berkeley vào năm 2009 [15, 16]. Nó cung cấp rất nhiều tính năng cho việc xử lý nhanh chóng dữ liệu lớn. Spark
Core là thành phần chính của Apache Spark, là công cụ thực thi chung cơ bản cho nền tảng Spark mà tất cả các chức
năng khác được xây dựng trên cùng. Nó cung cấp các khả năng tính toán trong bộ nhớ để cung cấp tốc độ, một mô hình
thực thi tổng quát để hỗ trợ nhiều ứng dụng và cung cấp các API cho các ngôn ngữ lập trình phổ biến như Java, Scala và
Python để dễ dàng phát triển.
Khi nhận được một tác vụ để xử lý, Spark cho phép chia nhỏ tác vụ ra thành nhiều phần có thể thực hiện song song được.
Spark sẽ thực thi các tác vụ này trên cụm tính toán từ nhiều máy khác nhau. Spark tận dụng khả năng xử lý trên RAM
để khai thác tốc độ xử lý nhanh, nhờ đó mà nó có thể tăng tốc xử lý hơn so với Hadoop.
Tuy nhiên có một đặc điểm đó là Spark không cung cấp hệ thống lưu trữ phân tán của riêng nó (distributed-storage). Vì
vậy khi sử dụng Spark, thông thường cần cài đặt thêm phần mềm hỗ trợ cho lưu trữ dữ liệu phân tán. Đó cũng là lý do
người dùng thường cài đặt Spark trên nền Hadoop để sử dụng cơ chế lưu trữ dữ liệu HDFS của Hadoop. Một trong những
điều tạo nên sự khác biệt giữa Spark và Hadoop đó là Spark nạp dữ liệu lên bộ nhớ và xử lý, tái sử dụng lại dữ liệu đã
lưu trên bộ nhớ thay vì phải đọc ghi liên tục vào HDFS như Hadoop.
B. Bloom Filter
Bộ lọc Bloom [24] được Burton Howard Bloom đề xuất năm 1970, là một cấu trúc dữ liệu xác suất không gian hiệu quả
dùng để kiểm tra xem một phần tử có là thành viên của một tập hợp hay không. Kết quả dương tính giả (false positive)
là có khả năng xảy ra nhưng kết quả âm tính giả (false negative) là không xảy ra. Phần tử dương tính giả là phần tử được
bộ lọc xác định là thuộc tập dữ liệu ban đầu nhưng thực ra nó không thuộc tập dữ liệu đó. Phần tử âm tính giả là phần tử
được bộ lọc xác định là không thuộc tập dữ liệu ban đầu nhưng thực ra nó lại thuộc tập dữ liệu đó.
Bộ lọc Bloom rỗng là một mảng bits gồm m bits, tất cả được đặt thành giá trị 0. Cần có k hàm băm khác nhau được xác
định, mỗi hàm ánh xạ hoặc băm các phần tử được đặt thành một trong các vị trí mảng m, tạo ra phân phối ngẫu nhiên
thống nhất. Thông thường, k là hằng số, nhỏ hơn nhiều so với m; sự lựa chọn chính xác của k và hằng số tỷ lệ của m được
xác định bởi tỷ lệ dương tính giả dự định của bộ lọc. Để thêm một phần tử, cần sử dụng k hàm băm để có được k vị trí
trong mảng bits. Đặt các bit ở tất cả các vị trí này thành 1.

Hình 1. Cấu trúc bộ lọc Bloom


C. Hoạt động Join trong MapReduce
MapReduce được Google giới thiệu lần đầu tiên vào năm 2004 đã được sử dụng trong nhiều thao tác tính toán trên những
tập dữ liệu lớn [1]. MapReduce với hai thao tác chính là Map và Reduce. Thao tác Map được áp dụng trên dữ liệu đầu
vào và cho ra sản phẩm trung gian là danh sách các cặp key-value. Những cặp key-value này sẽ được đưa về các Reducer
có cùng key. Reducer sẽ kết hợp các value của cùng một key để cho ra kết quả cho key đó.
Mô hình MapReduce được sử dụng phổ biến trong việc xử lý công việc trên các tập dữ liệu lớn một cách song song sử
dụng một cụm gồm nhiều máy tính kết nối với nhau. Hai giai đoạn map và reduce được thực hiện với nhiều tác vụ map
Triệu Thanh Ngoan, Phan Anh Cang, Phan Thượng Cang 3

và nhiều tác vụ reduce được chạy đồng thời trên nhiều nút tính toán giúp cho công việc được thực hiện một cách nhanh
chóng hiệu quả hơn.
Join [3] là thao tác kết hợp các tuples từ những tập dữ liệu khác nhau với những điều kiện Join. Để minh hoạ cho hoạt
động join trong môi trường MapReduce, chúng ta xem xét xử lý join cho hai tập dữ liệu lớn R(v, k1) và S(k2, w) như hình
sau.

Hình 2. Hoạt động join trong môi trường MapReduce


Thao tác join trong MapReduce sẽ được diễn ra như mô tả trong Hình 2 với các bộ dữ liệu của R là {(A, B), (B, C), (A,
D), (A, C)} và các bộ dữ liệu của S là {(B, F), (D, E)}. Giai đoạn map chịu trách nhiệm đọc các khối dữ liệu đầu vào của
R và S, ba Mapper được tạo ra như trong Hình 1 để xử lý ba khối dữ liệu (mỗi khối sẽ gồm vài tuples). Các Mapper sẽ
biến đổi các tuples thành các cặp khoá (key, value) sao cho k1 và k2 là khoá join. Các cặp khoá key-value được gọi là các
bộ dữ liệu trung gian.
1: {(A, B), (B, C), (A, D)} → {(B, A), (C, B), (D, A)}
2: {(A, C)} → {(C, A)}
3: {(B, F), (D, E)} → {(B, F), (D, E)}
Các bộ dữ liệu trung gian với cùng khoá sẽ được đưa đến cùng Reducer. Hàm reduce đơn giản sẽ lấy mỗi bộ dữ liệu
trung gian của R kết hợp với một bộ dữ liệu trung gian của S để cho ra kết quả.
Có nhiều dạng câu truy vấn join khác nhau như: join hai chiều (two-way join), join đa chiều (multi-way join), hay join
đệ qui (recursive join). Trong ba dạng join trên thì join đệ qui là câu truy vấn khá phức tạp với chi phí lớn và được áp
dụng trong nhiều lĩnh vực đòi hỏi có sự tính toán lặp lại như PageRank[26] hoặc graph mining[29] trong các vấn đề như
Friend graph [25, 28] của mạng xã hội. Join đệ qui còn được gọi là fix-point join, với các thao tác join lặp đi lặp lại cho
đến khi việc lặp này không còn tạo ra được kết quả mới. Một ví dụ cụ thể cho thao tác join đệ qui là trong câu truy vấn
mối quan hệ của một người trong cơ sở dữ liệu gia đình.
Ancestor (X, Y)  Parent (X, Y)
Ancestor (X, Z)  Ancestor (X, Y) ⋈ Parent (Y, Z)
Một người X là tổ tiên của người Y khi người X là cha mẹ của Y. Một người X cũng là tổ tiên của người Z nếu tồn tại một
người Y sao cho X là tổ tiên của Y và Y là cha mẹ của Z.
D. Các thuật toán bao đóng bắc cầu
Bao đóng bắc cầu là ma trận khả năng tiếp cận để đi được từ đỉnh u đến đỉnh v của một đồ thị. Với một đồ thị được đưa
ra, phải tìm một đỉnh v có thể đi được từ một đỉnh u khác, cho tất cả các cặp đỉnh (u, v) [6, 27]. Đã có nhiều nghiên cứu
điều tra về các thuật toán tính bao đóng bắc cầu (transitive closure) trên các cơ sở dữ liệu quan hệ lớn.
Các thuật toán tính bao đóng bắc cầu có thể được chia ra làm hai loại là các thuật toán tính trực tiếp và các thuật toán
lặp. Các thuật toán tính trực tiếp không xem xét vấn đề ở khía cạnh đệ qui và có điểm bắt đầu là một ma trận logic [22].
4 MỘT ĐỀ XUẤT CẢI TIẾN THUẬT TOÁN JOIN ĐỆ QUI TRÊN TẬP DỮ LIỆU LỚN

Các thuật toán tính toán trực tiếp thường thấy như Warshall [18], Warren [19], và Schmitz [20]. Loại thứ hai là các thuật
toán lặp được phát triển trong bối cảnh tính toán các câu truy vấn đệ qui. Các thuật toán này không sử dụng cấu trúc đặc
biệt của một vấn đề bao đóng bắc cầu. Ở thuật toán lặp này, có thể chia thành hai loại nhỏ là tuyến tính (Naive [21],
Semi-Naive [21]) và phi tuyến tính (Smart [6, 23]).
Giải thuật Semi-Naive để tính bao đóng bắc cầu cho đồ thị K có thể được biểu thị như sau:
F = K, ΔF = K;
while ΔF ≠ ∅ do
ΔF = ΔF ⋈ K – F
F = F ∪ ΔF
end
Ở mỗi lần lặp của vòng lặp while, F được cập nhật bằng cách nối F với các cạnh của đồ thị ban đầu, K. Trên lần lặp n,
∆F chứa tất cả các cặp nút sao cho đường đi ngắn nhất giữa chúng có độ dài n + 1. Các cặp này không thể được phát hiện
trong vòng lặp trước (nhờ đường đi ngắn nhất giữa chúng có độ dài n + 1) . Nếu bất kỳ cặp nào được tạo bởi phép nối đã
được tìm thấy, thì điều này có nghĩa là tồn tại một đường đi ngắn hơn giữa hai nút được tìm thấy trên lần lặp trước. Phép
trừ F được thiết lập để loại bỏ bất kỳ bộ dữ liệu nào như vậy. Vào cuối lần lặp n, mỗi bộ dữ liệu trong ∆F đại diện cho
một bộ dữ liệu mới được phát hiện trong bao đóng bắc cầu.
Smart chia sẻ với thuật toán tuyến tính thuộc tính đó là mong muốn việc khám phá mỗi đường đi ngắn nhất chỉ một lần
[23]. Trên mỗi lần lặp, nó kết hợp các đường dẫn có độ dài bằng số mũ của 2 với các đường dẫn có độ dài nhỏ hơn. Theo
cách này, nó có thể tính toán bao đóng bắc cầu trong một số logarit vòng lặp trong khi lấy được các cặp trùng lặp ít hơn
nhiều so với thuật toán phi tuyến tính tiêu chuẩn. Giải thuật Smart để tính bao đóng bắc cầu cho đồ thị K có thể được
biểu thị như sau:
Q = Edges
P=∅
while Q ≠ ∅ do
ΔP = Q ⋈ P
P = Q ∪ P ∪ ΔP
Q=Q⋈Q–P
end
Các kết quả thử nghiệm [2] cho thấy Semi-Naive là lựa chọn tốt nhất để tính toán bao đóng bắc cầu của các đồ thị lớn
trong mô hình MapReduce. Đối với tất cả các đồ thị phi cây (non-tree graphs) được thử nghiệm, hiệu suất của Semi-
Naive vượt xa hoặc ít nhất là tương đương với Smart.
III. CẢI TIẾN THUẬT TOÁN JOIN ĐỆ QUI TRÊN TẬP DỮ LIỆU LỚN
A. Giải thuật Semi-Naive cho join đệ qui
Semi-Naive [2, 4, 6, 17] là một giải thuật tính toán bao đóng bắc cầu tuyến tính khá phổ biến và phù hợp để triển khai
trong môi trường MapReduce. Giải thuật Semi-Naive cho Join đệ qui – tạm gọi là giải thuật RJ2 – được trình bày cụ thể
như sau:
Bảng 1. Thuật toán Semi-Naive cho join đệ qui

Thuật toán Semi-Naive cho join đệ qui – RJ2

F0 = K; F0 = K; i = 1; (1)

do (2)

Oi = Fi-1 (c1, c2) ⋈c2=c1’ K (c1’, c2’) (3)

Fi = Oi – Fi-1 (4)

Fi = Fi-1  Fi (5)

i++ (6)

while Fi ≠ Ø (7)


Triệu Thanh Ngoan, Phan Anh Cang, Phan Thượng Cang 5

K biểu thị cho đồ thị ban đầu. Khởi tạo F với K, F sẽ chứa tất cả tuples trong bao đóng bắc cầu của đồ thị cho đến cuối
giải thuật. ΔF chứa các tuples mới được tạo ra từ vòng lặp trước đó. Tại mỗi lần lặp trong vòng lặp do-while, ΔF sẽ được
cập nhật bằng cách join ΔF với K.
Giải thuật Semi-Naive cho join đệ quy sẽ được thực hiện bởi hai nhóm công việc lặp đi lặp lại. Nhóm công việc join thực
hiện thao tác join các tuples và nhóm công việc tính toán tập dữ liệu tăng cường để loại bỏ những tuples trùng lắp đã tìm
thấy trong kết quả trước đó.
Tại lần lặp thứ i, công việc join sẽ thực hiện join ΔFi-1 với K để tạo ra tập dữ liệu trung gian Oi. Trong tập dữ liệu trung
gian Oi này sẽ có những tuples đã được tìm thấy trước đó, công việc tính tập dữ liệu tăng cường sẽ thực hiện nhiệm vụ
loại bỏ các tuples trùng lắp này (Oi – Fi-1). Cuối mỗi vòng lặp, ΔF sẽ chứa những tuples mới được tìm thấy cho lần lặp
tiếp theo.
Semi-Naive tốt hơn so với Naive ở điểm là nó tránh đi việc lặp lại thao tác join tập F và K tại mỗi lần lặp. Nó chỉ cho
phép các tuples mới tham gia vào trong thao tác join, kết quả join có thể trùng lắp với kết quả trước đó và sẽ bị loại bỏ
bởi thao tác tính tập dữ liệu tăng cường.
B. Đề xuất giải thuật Semi-Naive cải tiến cho join đệ qui
Tại dòng thứ (3) của giải thuật Semi-Naive trình bày phía trên, chúng ta có thể thấy được rằng tại mỗi lần lặp thì tập dữ
liệu K là không đổi. Công việc quan trọng nhất trong giải thuật Semi-Naive là công việc join bộ dữ liệu K với bộ dữ liệu
ΔF. Như vậy nếu có n lần lặp thì tập K sẽ được Join n lần. Nếu chúng ta thay đổi thao tác join hai chiều bằng cách tăng
thêm một tập dữ liệu K nữa để có thao tác join ba chiều thì chúng ta đã thực hiện hai lần thao tác join tập dữ liệu K trong
cùng một lần lặp cho nên số lần lặp cần thiết sẽ giảm đi 2 lần. Giải thuật Semi-Naive cải tiến cho join đệ qui – tạm gọi
là giải thuật ORJ3 – được mô tả như sau:
Bảng 2. Thuật toán Semi-Naive cải tiến cho join đệ qui

Thuật toán Semi-Naive cải tiến cho join đệ qui - ORJ3

F0 = K; F0 = K; i = 1; (1)

do (2)

Oi = Fi-1 (c1, c2) ⋈c2=c1’ K (c1’, c2’) ⋈c2’=c1’ K (c1’, c2’) (3)

Fi = Oi – Fi-1 (4)

Fi = Fi-1  Fi (5)

i++ (6)

while Fi ≠ Ø (7)

Như vậy rõ ràng rằng số lần lặp của giải thuật ORJ3 sẽ giảm đi hai lần, hoặc nói cách khác thì một lần lặp của giải thuật
này sẽ tương đương 2 lần lặp của giải thuật Semi-Naive ban đầu. Trong việc đề xuất như trên ta thấy được có sự xuất
hiện của thao tác join ba chiều.

Hình 3. Giải thuật Một lần join ba chiều [14]


Tính toán join ba chiều trên ba tập dữ liệu R(A, B, V) ⋈ S(B, C, W) ⋈ T(C, D, X) có thể được thực hiện theo cách đầu
tiên tính join của R và S sau đó lấy kết quả join với T hoặc ngược lại. Tạm gọi cách này là Hai lần join hai chiều 2,3J vì
nó thực hiện hai lần công việc MapReduce. Afrati and Ullman [12, 13] đã đề xuất thực hiện một lần công việc MapReduce
cho việc join ba chiều và chúng ta tạm gọi là Một lần join ba chiều (1,3J) [14]. Đối với việc thực hiện Một lần join ba
6 MỘT ĐỀ XUẤT CẢI TIẾN THUẬT TOÁN JOIN ĐỆ QUI TRÊN TẬP DỮ LIỆU LỚN

chiều thì số lượng Reducers cần sử dụng là một tham số tường minh k = k1*k2. Chúng ta tạo ra hai hàm hash h và g tương
ứng với số lượng slots k1 và k2. Mappers sẽ tạo ra một cặp key-value cho mỗi tuple trong tập dữ liệu S, k1 và k2 cặp key-
value cho mỗi tuple trong tập dữ liệu T và R.
Hình 3 mô tả cách giải thuật Một lần join ba chiều chuyển các bộ dữ liệu đến Reducers. Các cặp key-value của R và T
được gửi đến các hàng và cột trong ma trận Reducers, cặp key-value của S thì được gửi đến một Reducers để thực hiện
xử lý join tại đó.
Trong nghiên cứu [10] của T.C.Phan và đồng nghiệp đã chỉ ra rằng giải thuật Một lần join ba chiều với ba tập dữ liệu
R(A, B) ⋈ K(B, C) ⋈ L(C, D) sẽ tốt hơn so với Hai lần join hai chiều với điều kiện r < (|R|.α)2, với r là số lượng Reducers,
|R| = |K| = |L|, và α là xác suất của hai tuples từ các tập dữ liệu khác nhau có cột khoá join trùng khớp. Kết luận này
được đưa ra khi xem xét kích thước của tập dữ liệu trung gian được sinh ra từ hai giải pháp join trên như sau:
| | , Một lần Join ba chiều
|𝐷| = {2 . 𝑅2 . √𝑟
|𝑅| . 𝛼 , Hai lần Join hai chiều

Lượng dữ liệu trung gian sinh ra càng lớn thì chi phí truyền thông càng tăng kéo theo chi phí xử lý Join càng lớn. Nghiên
cứu [10] đã cho thấy lượng dữ liệu trung gian sinh ra của Một lần join ba chiều là ít hơn. Chúng tôi sẽ sử dụng giải thuật
Một lần join ba chiều cho việc tối ưu hoá join đệ qui. Lưu đồ giải thuật Semi-Naive cải tiến cho join đệ qui ORJ3 được
thể hiện trong hình 4.
Ngoài ra để giảm bớt số dữ liệu không cần thiết tham gia vào thao tác join, chúng tôi xây dựng hai bộ lọc Bloom cho
việc lọc dữ liệu đầu vào trước khi phát ra trên các Reducers. Để có một bộ lọc BF cần tạo ra một mảng bits với m phần
tử và k hàm hash (m = 120,000 và k = 8). Hai bộ lọc Bloom một cho việc lọc tập dữ liệu K và một cho việc lọc tập dữ
liệu ΔF, tương ứng với bộ lọc BFΔF và BFK.

Hình 4. Lưu đồ giải thuật ORJ3


IV. THỰC NGHIỆM
A. Cụm máy tính và phương thức đánh giá
Tiến hành cài đặt Spark cluster trên hệ thống máy tính gồm 1 máy chủ và 10 máy con được cung cấp bởi phòng thí
nghiệm Mạng di động và Dữ liệu lớn của Khoa CNTT&TT, Đại học Cần Thơ. Máy tính được cài ứng dụng Spark cluster
thành 10 nút worker với cấu hình 5 CPUs, 8GB RAM, và 100GB ổ cứng. Hệ điều hành cài đặt là Ubuntu 18.04 LTS.
Phiên bản các phần mềm cài đặt trên nút: Hadoop 3.0.3, Spark 2.4.3, Java 1.8.
Dữ liệu được sử dụng trong thực nghiệm là từ nguồn PUMA Benchmarks với dung lượng là 1GB, 5GB, 10GB, 15GB,
20GB và 25GB tương ứng với 2.6, 13.5, 26.8, 40.2, 53.6 và 67.1 triệu dòng dữ liệu. Các tập dữ liệu lưu trữ ở dạng textfile
với 19 trường dữ liệu mỗi dòng ngăn cách bởi dấu phẩy và 19 ký tự dữ liệu mỗi cột.
Thực nghiệm sẽ tiến hành đánh giá giải thuật RJ2 với cách thực hiện Hai lần join hai chiều thông thường và cách thực
hiện giải thuật Semi-Naive cải tiến cho join đệ qui ORJ3. Trên mỗi tập dữ liệu thực nghiệm, sẽ tiến hành ghi nhận lại
Triệu Thanh Ngoan, Phan Anh Cang, Phan Thượng Cang 7

lượng dữ liệu trung gian cần vận chuyển qua mạng, thời gian thực thi và số vòng lặp tương ứng cho việc phân tích và so
sánh.
B. Kết qủa
Thời gian thực thi cụ thể bởi mỗi hướng tiếp cận được ghi lại theo đo vị đo giây. Có thể thấy rõ ràng sự khác biệt là rất
lớn với giải thuật RJ2 và ORJ3.

Hình 5. Thời gian thực thi giữa hai hướng tiếp cận
Kết quả ở Hình 5 cho thấy rõ rệt hiệu quả của việc cải tiến với giải thuật ORJ3 so với giải thuật RJ2, hiện rõ ở tốc độ xử
lý. Cách thực hiện thao tác join ba chiều thay vì join hai chiều trong giải thuật Semi-Naive đã giúp cho thời gian thực thi
giảm đi nhiều. Tuy nhiên, đối với lượng dữ liệu ít thì tốc độ xử lý không được cải thiện đáng kể. Điều này có thể được
lý giải bởi ORJ3 có thao tác tiền xử lý dữ liệu để xây dựng bộ lọc loại bỏ dữ liệu dư thừa không tham gia vào thao tác
join. Nếu lượng dữ liệu ít thì sẽ tốn thời gian cho việc tiền xử lý này nên không mang lại hiệu quả đáng kể.

Hình 6. Lượng dữ liệu trung gian giữa hai hướng tiếp cận
Hình 6 mô tả lượng dữ liệu trung gian cần vận chuyển qua mạng cho thao tác join đệ qui. Số lượng vòng lặp giảm làm
cho số công việc MapReduce giảm, từ đó giúp cho lượng dữ liệu trung gian được giảm thiểu đáng kể. Bên cạnh đó bộ
lọc Bloom và cơ chế bộ nhớ đệm trong Spark cũng giúp ích rất nhiều cho việc làm giảm dữ liệu dư thừa không tham gia
vào thao tác join nhằm tối ưu hơn cho join đệ qui.
Số vòng lặp tương ứng với các cách tiếp cận cũng được ghi nhận lại. Chúng ta có thể thấy rằng số vòng lặp của giải thuật
ORJ3 giảm đi 2 lần so với RJ2. Cụ thể là:
NORJ3 = ⎡NRJ2 / 2⎤
Với NORJ3 là số vòng lặp của giải thuật ORJ3 và NRJ2 là số vòng lặp của giải thuật RJ2.
Bảng 3. Số vòng lặp tương ứng giữa hai hướng tiếp cận

Dữ liệu GB

1GB 5GB 10GB 15GB 20GB 25GB


Tiếp cận (vòng)

RJ2 4 4 6 9 11 11
ORJ3 2 2 3 5 6 6
8 MỘT ĐỀ XUẤT CẢI TIẾN THUẬT TOÁN JOIN ĐỆ QUI TRÊN TẬP DỮ LIỆU LỚN

V. KẾT LUẬN
Nghiên cứu này đã đưa ra giải pháp cụ thể mang lại hiệu quả cho vấn đề tối ưu hoá join đệ qui trong môi trường
MapReduce. Những đề xuất được thực hiện trong nghiên cứu này bao gồm: (1) Tận dụng tập dữ liệu K là không đổi qua
mỗi lần lặp, nghiên cứu đã đề xuất sử dụng giải thuật Một lần join ba chiều thay thế cho việc sử dụng Join hai chiều
nhằm giảm số vòng lặp và số công việc MapReduce; (2) Tận dụng khả năng xử lý lặp cung cấp bởi Apache Spark RDD;
(3) Tận dụng cơ chế vùng nhớ đệm của Spark để cache tập dữ liệu không đổi nhầm giảm thiểu chi phí có liên quan; (4)
Sử dụng bộ lọc nhằm loại bỏ phần nào dữ liệu dư thừa không tham gia vào thao tác Join.
Những kết quả chính của nghiên cứu này là:
 Đề xuất thuật toán Semi-Naive cải tiến cho join đệ qui tập dữ liệu lớn sử dụng join ba chiều và bộ lọc trong
MapReduce của Spark
 Có được các kết quả thực nghiệm cho Join đệ qui dữ liệu lớn
 Bổ sung gói join ba chiều và join đệ qui cho nền tảng xử lý dữ liệu lớn thế hệ mới Spark
Thông qua thực nghiệm, nghiên cứu đã cho thấy được hiệu quả của việc cải tiến join đệ qui. Đây là một đóng góp mang
tính thực tiễn cao vì giải thuật Semi-Naive là giải thuật rất thường được sử dụng trong join đệ qui với môi trường dữ liệu
lớn.
VI. TÀI LIỆU THAM KHẢO
[1] J. Dean and S. Ghemawat, “MapReduce: Simplified Data Processing on Large Clusters,” Commun ACM, vol. 51,
no. 1, pp. 107–113, Jan. 2008.
[2] G. Eric, “Distributed Algorithms for the Transitive Closure.”, 2013.
[3] T.-C. Phan, “Optimization for big Joins and recursive query evaluation using intersection and difference filters in
MapReduce”, PhD Thesis, 2014.
[4] B. François and R. Ramakrishnan, “An Amateur's Introduction to Recursive Query Processing Strategies.”,
SIGMOD Conference, 1986.
[5] Chen, Yangjun, “On the bottom - up evaluation of recursive queries.”, Int. J. Intell. Syst. 11, 807-832, 1996.
[6] Yannis E. Ioannidis, “On the Computation of the Transitive Closure of Relational Operators”, In Proceedings of the
12th International Conference on Very Large Data Bases (VLDB '86), San Francisco, CA, USA, 403-411, 1986.
[7] F. N. Afrati, V. Borkar, M. Carey, N. Polyzotis, and J. D. Ullman, “Map-reduce Extensions and Recursive Queries,”
in Proceedings of the 14th International Conference on Extending Database Technology, New York, NY, USA,
2011, pp. 1–8.
[8] M. Shaw, P. Koutris, B. Howe, and D. Suciu, “Optimizing Large-scale Semi-NaïVe Datalog Evaluation in Hadoop”,
in Proceedings of the Second International Conference on Datalog in Academia and Industry, Berlin, Heidelberg,
2012, pp. 165–176.
[9] T. C. Phan, T. T. Q. Tran, and A. C. Phan, “Tối ưu hóa Join đệ quy trên tập dữ liệu lớn trong môi trường spark”,
Nghiên cứu cơ bản và ứng dụng Công nghệ thông tin (FAIR'9); Cần Thơ, 08/2016.
[10] T.-C. Phan, L. d’Orazio, and P. Rigaux, “A Theoretical and Experimental Comparison of Filter-Based EquiJoins in
MapReduce,” in Transactions on Large-Scale Data- and Knowledge-Centered Systems XXV, A. Hameurlain, J.
Küng, and R. Wagner, Eds. Springer Berlin Heidelberg, 2016, pp. 33–70.
[11] T. C. Phan, L. d’Orazio, and P. Rigaux, “Toward Intersection Filter-based Optimization for Joins in MapReduce,”
in Proceedings of the 2Nd International Workshop on Cloud Intelligence, New York, NY, USA, 2013, p. 2:1–2:2.
[12] F. N. Afrati and J. D. Ullman, “Optimizing joins in a map-reduce environment.”, In EDBT, pages 99–110, 2010.
[13] F. N. Afrati and J. D. Ullman, “Optimizing multiway joins in a mapreduce environment.”, IEEE Trans. Knowl. Data
Eng., 23(9):1282–1298, 2011.
[14] B. Kimmett, A. Thomo, S. Venkatesh, "Three-way joins on mapreduce: An experimental study", IISA, 2014
[15] Apache Spark [Online]. Available: https://databricks.com/spark/about retrieved July 10, 2019
[16] Apache Spark [Online]. Available: https://spark.apache.org retrieved July 10, 2019
[17] Apache Hadoop [Online]. Available: https://hadoop.apache.org retrieved July 15, 2019
[18] S. Warshall, A Theorem on Boolean Matrices, J. ACM 9, 1 (Jan. 19621, 11-12)
[19] H. S. Warren, A Modification of Warshall’s Algorithm for the Transitive Closure of Binary Relations, Commun.
ACM 18, 4 (April 1975), 218-220.
[20] L. Schmitz, “An Improved Transitive Closure Algorithm”, Computing 30, (1983), 359-371
Triệu Thanh Ngoan, Phan Anh Cang, Phan Thượng Cang 9

[21] F. Bancilhon, “Naive Evaluation of Recursively Defined Relations”, Tech. Rept. DB-004-85, MCC, Austin, Texas,
1985
[22] A. Rakesh & V. H. Jagadish, “Direct Algorithms for Computing the Transitive Closure of Database Relations”,
1987, 255-266.
[23] F. N. Afrati and J. D. Ullman, “Transitive closure and recursive datalog implemented on clusters” In Proceedings of
the 15th International Conference on Extending Database Technology, pages 132–143. ACM, 2012.
[24] B. H. Bloom, “Space/time trade-offs in hash coding with allowable errors,” Commun. ACM, vol. 13, no. 7, pp. 422–
426, Jul. 1970
[25] S. Jiwon, S. Guo, M. S. Lam, “SociaLite: Datalog extensions for efficient social network analysis”, 278-289.
10.1109/ICDE.2013.6544832.
[26] J. Tahseen, F. Ubaida, B. Mirza, M. Saba, “A Survey and Comparative Study of Different PageRank Algorithms”,
International Journal of Computer Applications. 120. 24-30. 10.5120/21410-4444, 2015.
[27] I. Yannis, R. Raghu “Efficient Transitive Closure Algorithms”. Proceedings of the 14th VLDB Conference. (1988)
382-394.
[28] Leskovec, J., Rajaraman, A., & Ullman, J. (2014). “Mining Social-Network Graphs”, In Mining of Massive Datasets
(pp. 325-383). Cambridge: Cambridge University Press. doi:10.1017/CBO9781139924801.011
[29] Seufert, S., Anand, A., Bedathur, S.J., & Weikum, G. (2012). “High-Performance Reachability Query Processing
under Index Size Restrictions” ArXiv, abs/1211.3375.
AN EFFICIENT APPROACH FOR IMPROVING RECURSIVE JOIN
ALGORITHM ON LARGE DATASETS
Trieu Thanh Ngoan, Phan Anh Cang, Phan Thuong Cang
ABSTRACT— In the evolution of Big Data, processing large dataset quickly and effectively is always of interest to researchers. In
Big data computation, Join operation is a common operation, appearing in many data query operations, especially Recursive Join.
This activity repeats two tasks, which are computing transitive closure and differences. Those tasks generate plenty of intermediate
data and data transmissions over the network. It can be said that Join operation is a costly task that reduces the performance of
queries in large datasets. Therefore, this thesis was conducted to optimize Semi-Naïve algorithm for Recursive Join on large datasets
using three-dimensional Join algorithm and filtering in Spark’s MapReduce environment. This improvement reduces the number of
iterations, the number of necessary MapReduce jobs needed, and reduces redundant data which is not necessary for Join operation.
From the cost model and experiments, it is shown that this study has significantly improved the performance of recursive Join queries
in large datasets.

You might also like