Ví dụ cụ thể cho thấy điểm yếu của RDBMS và điểm mạnh của NoSQL
NoSQL ra đời như là một giải pháp cho bài toán về độ co giãn (scalability), độ linh hoạt (flexibility) và performance phát sinh ở RDBMS. Dưới đây, chúng ta sẽ cùng xem một ví dụ cụ thể để thấy vấn đề khó khăn trong việc mở rộng (scale) database ở RDBMS và cách mà NoSQL giải quyết vấn đề này.
Cơ sở dữ liệu “Contact” ở kiến trúc RDBMS
Giả sử chúng ta muốn xây dựng kiến trúc Database cho một “Contact” Application với mô hình RDBMS. Chúng ta có thể nghĩ đến table contact các trường cơ bản như sau:
– id
– title
– firstname
– lastname
– gender
– telephone
– address
– city
– region
– zipcode
– country
Nếu như quay lại thời điểm của vài mươi năm trước, khi mà số người sở hữu điện thoại di động chỉ đếm trên đầu ngón tay, thì Database trên nhìn chung là không gặp vấn đề gì. Thế nhưng, trong bối cảnh hiện nay, dễ thấy Database trên gặp phải các khó khăn như sau:
Khó khăn thứ 1: Bao nhiêu trường để lưu số điện thoại là đủ? Và email, địa chỉ nhà?
Rất ít người chỉ có duy nhất một số điện thoại. Một người đang đi làm sẽ có thể sở hữu 1 số điện thoại cá nhân, 1 số điện thoại của Công ty, và 1 số điện thoại bàn. Sẽ có những người sở hữu trên 2 số điện thoại cá nhân, và cũng có những người sở hữu hơn 2 số điện thoại bàn.
Như vậy, nếu ta thêm các trường telephone1, telephone2, telephone3…vv… vào bảng trên, ta sẽ thấy xuất hiện 2 vấn đề:
– Thứ nhất, dù ta có dự phòng đến 3 trường lưu số điện thoại, vẫn sẽ có rắc rối với người sở hữu nhiều hơn 3.
– Thứ hai, ngược với vấn đề thứ nhất, đó là ta sẽ bị thừa rất nhiều bộ nhớ cho những record chỉ có 1, hoặc thậm chí không có số điện thoại nào!
Để giải quyết 2 vấn đề trên, thì một phương án khả thi trong trường hợp này đó là tách trường telephone ra thành một table riêng. Ta sẽ có table telephone với các trường cơ bản như:
– contact_id
– number
– telephone_type
Với email, ta cũng gặp trường hợp tương tự. Và thế là một table email nữa ra đời:
– contact_id
– email_address
– email_type
Tương tự, một người cũng có thể có nhiều địa chỉ nhà khác nhau, vậy là cần thêm table address:
– contact_id
– address_type
– city
– region
– zipcode
– country
– address_detail
Tạm thời tổng kết lại, table contact ban đầu được thu gọn về như sau:
– id
– title
– firstname
– lastname
– gender
Vậy là table contact với rất nhiều trường đã được thu gọn lại chỉ còn 5 trường như trên! Trông thật tuyệt!
Có vẻ như các khó khăn “đồng dạng” với khó khăn thứ 1 này đều có thể giải quyết được bằng việc tách table riêng ra như trên. Thế nhưng, đó cũng là lúc khó khăn thứ 2 tìm đến!
Khó khăn thứ 2: quá nhiều table với các quan hệ chằng chịt dẫn đến tốn một lượng traffic khổng lồ để query
Cứ thử hình dung một người có 3 số điện thoại, 5 email và 2 địa chỉ, như vậy một câu Query SQL sẽ trả về 3 x 5 x 2 = 30 kết quả!
Đó là chưa kể Database này sẽ còn dễ dàng “phình” to lên. Giả sử như danh bạ này được dùng cho nội bộ của một Công ty có quy mô trung bình – lớn, thì ta dễ dàng tưởng tượng được sẽ có thêm một số table riêng biệt khác cho phòng ban, chức vụ, project…vv… Lúc này, hao phí để query kết quả cho chỉ 1 contact cũng sẽ trở nên vô cùng lớn.
Khi đó, nếu đột nhiên người ta phát sinh nhu cầu search fulltext cho hệ thống danh bạ này, thì chắc việc fulltext cũng khó lòng hiện thực được, do ta phải thực hiện search ở toàn bộ các table. (Khái niệm fulltext search sẽ được giới thiệu ở một bài khác).
Khó khăn thứ 3: điều gì sẽ xảy ra nếu ta có nhu cầu thêm một số trường khác?
Ở thời điểm bắt đầu thiết kế hệ thống, người ta chỉ có nhu cầu lưu trữ tên, họ, giới tính, số điện thoại, email và địa chỉ của nhân viên.
Thế nhưng, một thời gian sau khi hệ thống đã chạy, người ta nhận ra rằng họ muốn lưu thêm các nội dung khác, chẳng hạn như các tài khoản mạng xã hội (Facebook, Twitter, LinkedIn, vv…), chức vụ, phòng ban, ghi chú… vv…
Bất cứ ai đã từng làm việc với RDBMS đều hiểu là, việc thay đổi cấu trúc của một table gây ảnh hưởng rất nhiều và tốn rất nhiều công sức. Cho dù chỉ là mối quan hệ 1-1, chẳng hạn như một nhân viên chỉ đang giữ duy nhất 1 chức vụ, ta vẫn cần nhiều thời gian để fill đầy thông tin cho trường “position” ở tất cả mọi record. Dĩ nhiên, sẽ là “ác mộng” khi phải xử lý thêm mới một mối quan hệ n-n, ví dụ như một nhân viên có thể làm việc ở nhiều projects, và một project thì có nhiều nhân viên tham gia.
Sử dụng NoSQL để giải quyết vấn đề như thế nào?
Dữ liệu của các contact liên quan đến con người. Đó là các dữ liệu không thể đoán trước và có các yêu cầu khác nhau tại các thời điểm khác nhau. Việc xây dựng danh bạ sẽ được hưởng lợi từ việc sử dụng cơ sở dữ liệu NoSQL, có thể lưu trữ tất cả dữ liệu của một cá nhân vào một tài liệu lưu trữ duy nhất trong tập contacts:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
{
name: [
"Tang", "Minh", "Triet"
],
company: "VTI Japan",
telephone: {
home: "0123456789",
mobile: "9876543210",
work: "2244668800"
},
email: {
personal: "triet.tangminh@gmail.com",
work1: "triet.tangminh@vti.com.vn",
work2: "triet.tangminh@genba.com.vn"
},
address: {
home: {
street: "Đường số 1",
city: "Tokyo",
country: "Japan"
}
},
birthdate: 19xx-xx-xx,
facebook: 'secret',
hobby: "chinese-chess, game, Japanese"
note: "iOS",
photo: "abcdef.jpg"
}
|
Ở ví dụ này, ta thấy các trường mà nhân viên trên không có như là twitter, linkedin, project … thì sẽ không cần thiết phải lưu. Tương tự, ở nhân viên trên lại có những trường như hobby, photo… mà ở những nhân viên khác có thể không có! Đây chính là khả năng scalable gần như vô hạn của NoSQL.
Ngoài ra, dễ thấy toàn bộ thông tin đều được lưu vào duy nhất một NoSQL database là contacts, nên tốc độ query sẽ được cải thiện vô cùng lớn. Không còn phải thực hiện những câu lệnh JOIN thừa thãi nữa.
NoSQL có điểm yếu không?
NoSQL tỏ ra thật tuyệt vời khi nó giải quyết vấn đề đang mắc phải ở RDBMS thật dễ dàng. Thế nhưng, do tính chất “không có cấu trúc” (unstructured) và “không phụ thuộc” của NoSQL, thì ngược lại ta sẽ gặp khó khăn khi cần chỉnh sửa những nội dung vốn phụ thuộc với nhau.
Ví dụ, điều gì sẽ xảy ra khi một project… đổi tên, hay đơn giản hơn, kết thúc? Với RDBMS, dù cho quy mô dự án có lên đến hàng nghìn người đi nữa, thì ta chỉ việc thao tác (xóa đi hoặc đánh dấu là “done”) với duy nhất 01 record của project đó trong table project là đủ.
Ngược lại, ở NoSQL, nếu không thiết kế dữ liệu cẩn thận, thì với trường hợp trên ta sẽ phải truy xuất dữ liệu của toàn bộ database, tìm ra những record có thông tin project cần thay đổi và thay đổi nội dung của từng record đó. Việc này rất tốn thời gian, nếu không muốn nói là bất khả thi.
Kết luận
Ví dụ đơn giản trên đã cho thấy được sức mạnh của NoSQL đối với RDBMS trên phương diện scalability và performance. Tuy nhiên, nói như thế không có nghĩa là NoSQL sẽ có thể thay thế RDBMS. Chúng ta vẫn cần RDBMS ở những hệ thống mà database ít có sự biến đổi, đồng thời là những hệ thống cần có sự chuẩn xác tuyệt đối về transaction (mà điển hình là các hệ thống ngân hàng).
Tài liệu tham khảo:
– Wikipedia
– VIBLO