Database Denormalization
Đăng trong danh mục Web Programming bởi admin | Tags: chuan hoa, database, dbms, denormalization, join, large scale, normalization, rdbms, table
Đã lâu chưa viết bài về vấn đề kỹ thuật, nay viết bài này để chia sẽ tới các bạn một kỹ thuật trong nhóm các kỹ thuật tối ưu trong xây dựng ứng dụng web lớn (Large-scale Web Application), đó là kỹ thuật “Denormalization“. Ứng dụng lớn là các ứng dụng đòi hỏi khả năng chịu tải lớn và cần tối ưu về performance và tốc độ truy xuất database vì xu thế web bây giờ thao tác truy xuất database diễn ra rất thường xuyên.
Denormalization là kỹ thuật trong nhóm kỹ thuật tối ưu thiết kế cơ sở dữ liệu quan hệ (RDBMS). Như các bạn có được học thì hệ cơ sở dữ liệu quan hệ được thiết kế sử dụng mô hình BẢNG và sử dụng cột(Key) làm mối quan hệ. Và các bạn nếu có tìm hiểu thì cũng biết quá trình thiết kế cơ sở dữ liệu trải qua 3 bước Normalization (Chuẩn hóa) để dữ liệu được thiết kế sao cho tối ưu, không trùng lặp, dễ mở rộng và thay đổi.
Tuy nhiên, việc chuẩn hóa không phải lúc nào cũng phát huy hết tác dụng trong các ứng dụng thực tế. Ví dụ dưới đây là một mô hình database đã được chuẩn hóa cho chức năng tạo comment.

Như các bạn có làm qua cơ sở dữ liệu thì việc hiển thị thông tin comment với tên người gởi(sender) chỉ cần một câu lệnh JOIN để lấy thông tin của sender từ table User, ví dụ: “SELECT * FROM Comment INNER JOIN User ON c_senderid = u_id WHERE …”.
Đối với các ứng dụng nhỏ thì thao tác này chạy rất OK và database thiết kế như thế là đã chuẩn hóa rồi. Nhưng đối với các ứng dụng lớn, quá trình JOIN trong câu lệnh SELECT không phải là một thao tác nhanh và sẽ tốn thời gian xử lý phức tạp hơn vì cần phải JOIN 2 table. Trong trường hợp Table User quá lớn và table Comment cũng lớn thì việc JOIN trong câu lệnh SELECT sẽ là nổi ám ảnh cho ứng dụng của bạn.
Do gặp những tình huống như vậy, việc chuẩn hóa sẽ không tốt cho các câu lệnh SELECT cho ứng dụng dạng này nên kỹ thuật chuẩn hóa ngược (De-normalization) đã ra đời nhằm tăng tốc các câu lệnh SELECT và giảm việc JOIN khi không cần thiết. Dưới đây là mô hình database đã sử dụng kỹ thuật Denormalization, thêm một Field là c_senderusername để lưu thông tin người gởi mà không cần phải JOIN trong câu SELECT mới ra được username.

Vì đây gọi là quá trình chuẩn hóa ngược nên không nên sử dụng tùy tiện vì nó đi ngược lại quá trình chuẩn hóa, sẽ xảy ra quá trình douple dữ liệu cho một số field mà bạn sử dụng. Tuy nhiên, nếu sử dụng đúng chỗ thì kỹ thuật denormalization sẽ cải thiện nhiều cho các thao tác SELECT của bạn. Và nên nhớ, JOIN là nổi ám ảnh cho table lớn và LEFT JOIN (hay RIGHT JOIN) là nổi ám ảnh của nổi ám ảnh ^^.
Hy vọng bài viết giúp đỡ được phần nào cho việc thiết kế cơ sở dữ liệu cho ứng dụng “lớn” của bạn.
Bài viết liên quan:
8 Lời bình cho bài viết “Database Denormalization”
Viết lời bình
Bình luận mới nhất
- [Slide] Hội thảo: Heavy Web Optimization – Front-end
"Trên blog cá nhân của mình cũng có những bài viết cho việc tối ưu hóa " - TMQuang - phpmailer gởi mail SMTP bằng Gmail/Google Apps
"mình muốn đính kèm theo tập tin thì sao nhỉ" - Hòa - Mạng xã hội và thị trường Châu Á
"@admin, "Còn về mô hình “" - Dior - Lưu dữ liệu đa ngôn ngữ trong Database
"@viet_it_pro, cau truy " - viet_it_pro - Lưu dữ liệu đa ngôn ngữ trong Database
"@Quang Huỳnh, Bài bình luậ" - viet_it_pro - [Slide] Hội thảo: Heavy Web Optimization – Front-end
"Anh ơi cho em hỏi, làm thế nào để nhận mail google bằng php, anh có th" - Đặng Trung Kiên - Làm IT nên đọc ebook của nhà xuất bản nào?
"@Lê Hoàng Dũng, Mình thấy" - quang - Thư viện Khoa học tổng hợp TPHCM
"cảm ơn bài viết, mặc dù đã sinh sống ở Saigon khá lâu , nay mình mới c" - NHUNG - phpmailer gởi mail SMTP bằng Gmail/Google Apps
"Chào anh Tuấn, tut của anh em đã đọc, cảm ơn anh đã chia sẻ. Tuy nhiên" - Trần Đình Trọng - Review sách: Cuốn sách hoàn hảo về ngôn ngữ cơ thể
"Review chi tiết, nếu nhìn qua thì chưa chắc mình đã chú ý. Thanks!" - fire
Danh mục
- android (2)
- Business (24)
- Flash (1)
- Graphic Design (16)
- IT Guys (1)
- Javascript (9)
- Miscellaneous (58)
- Photography (9)
- PHP (38)
- Review sách (13)
- Search Engine Optimization (2)
- security (2)
- software (5)
- User Interface Design & Usability (8)
- Web Design (28)
- Web Programming (48)
Lưu trữ
- February 2012 (1)
- January 2012 (1)
- December 2011 (1)
- November 2011 (2)
- September 2011 (2)
- August 2011 (1)
- July 2011 (4)
- June 2011 (2)
- May 2011 (2)
- April 2011 (2)
- March 2011 (2)
- February 2011 (2)
- January 2011 (4)
- December 2010 (6)
- November 2010 (3)
- October 2010 (3)
- September 2010 (5)
- August 2010 (6)
- July 2010 (5)
- June 2010 (2)
- May 2010 (5)
- April 2010 (7)
- March 2010 (8)
- February 2010 (4)
- January 2010 (10)
- December 2009 (12)
- November 2009 (12)
- October 2009 (15)
- September 2009 (16)
- August 2009 (11)
- July 2009 (15)
- November 2008 (1)
- October 2008 (1)
- September 2008 (3)



April 7, 2010 at 3:54 pm
Thanks. Thi thoảng mình vẫn gặp mà giờ mới biết
[Reply]
April 9, 2010 at 8:48 am
Wow, hôm qua mới nói chiện zới Tòan ếch, hôm nay có rồi! Nhanh tè ^^
[Reply]
April 29, 2010 at 1:38 am
Trong thực tế đúng là phải chơi nhiều chiêu phá cách như thế! Ví dụ khác:
- 1 sản phẩm có nhiều hình, theo qui tắc đúng thì thiết kế 2 table: products và product_images. Tuy nhiên, ta có thể làm đơn giản hơn bằng cách tạo 1 table products, trong đó có field images. Giả sử hình ảnh chúng ta ko cần ghi chú thì field image sẽ chứa dữ liệu dạng như:
1.jpg@2.jpg@3.jpg
explode cái chuỗi trên với @ là ra đc array chứa 3 hình của sản phẩm! (@ có thể thay bằng các ký tự đặc biệt khác, miễn làm sao dự đoán đc cái ký tự đó ko bao giờ xuất hiện trong tên của hình là đc)
Ngoài ra, còn có thể áp dụng cho 1 ví dụ cụ thể khác:
- Nhân viên trong cty chịu sự quản lý của 1 hoặc nhiều người
- nv này và quản lý của nv đó mới đc xem ds khách hàng của họ
Theo lý thuyết, tạo 1 table users và 1 table user_manager để biểu diễn. Tuy nhiên, ta có thể dùng chuỗi để diễn đạt. Cụ thể, dùng 1 table users, có thêm cột manager, dữ liệu cột manager có dạng:
~1~2~3~4~
Với ~ là ký tự ngăn cách, 1-2-3-4 là id của manager (hoặc thay bằng username)
Chú ý, chuỗi này ko giống như ở trên, có thêm ký tự ngăn cách ở 2 đầu chuỗi, mục đích: hỗ trợ filter hoặc search.
Ví dụ: trên ds lọc ra những người thuộc quyền quản lý của manager có id = 1, phép so sánh sẽ là: … LIKE ‘%~’ + id_manager + ‘~%’
Nếu ko có dấu ~ ở đầu hoặc cuối thì sẽ ko lần ra đc id_manager ở đầu và cuối chuỗi.
Vài dòng chia sẻ!
[Reply]
admin Reply:
April 29th, 2010 at 7:41 am
Cảm ơn những chia sẽ quý báu của bạn.
[Reply]
May 6, 2010 at 3:18 pm
theo mình thấy nếu làm như bạn duy tuyên nói thì sẽ hơi khó khăn trong việc xóa và sửa giá trị đó
[Reply]
November 4, 2010 at 11:33 pm
” Ví dụ: trên ds lọc ra những người thuộc quyền quản lý của manager có id = 1, phép so sánh sẽ là: … LIKE ‘%~’ + id_manager + ‘~%’ ”
Select có % ở đầu trên 1 bảng lớn là cực kì chậm kể cả khi trường đó đã được đánh index .
[Reply]
admin Reply:
November 4th, 2010 at 11:38 pm
Cảm ơn bạn đã chia sẽ.
[Reply]
June 15, 2011 at 9:31 pm
@Duy Tuyên :
Như phần xử lý của anh . như vậy phải xử lý tên file ảnh , loại bỏ các kí tự được dùng để đánh dấu. Mình xinh chia sẽ . Chúng ta có thể lưu tên file ảnh vào 1 array .
Ví dụ :
$data = array(“ảnh_1.jpg”,”ảnh_2.jpg”,”ảnh_3.jpg);
sau đó dùng hàm : serialize($data) sẽ biến array đó thành chuỗi có các kí tự đặc biệt. Sau đó ta sẽ lưu vào field cần thiết.
Để hiển thị thì ta dùng unserialize($data) . Tức là dịch chuỗi kí tự đặc biệt thành array và hiển thị ra thôi.
Vậy tóm lại là serialize để mã hóa dữ liệu , unserialize để giải mã dữ liệu . /o_o\
[Reply]