PostgreSQL: View vs Materialized View (part 2)

22 tháng 08, 2018 - 1744 lượt xem

Chào mừng các bạn đến với phần 2 của series bài viết: View vs Materialized View

Trong phần trước, tôi đã trình bày về PostgreSQL View, xin được tóm tắt lại:

  • View giúp chúng ta "đóng gói" một câu query phức tạp vào trong 1 "object", giống như một function trong lập trình
  • Mỗi khi cần thực hiện đoạn query phức tạp kia, thay vì viết cả câu lệnh ra, ta chỉ cần SELECT từ View mà ta vừa tạo
  • PostgreSQL View chỉ lưu trữ câu query chứ không lưu trữ kết quả của câu query đó

Để giúp chúng ta vừa lưu trữ câu lệnh query, vừa lưu trữ cả kết quả của câu lệnh, PostgreSQL cung cấp cho chúng ta một kiểu View khác: Materialized View.

Như thường lệ, hãy bắt đầu bằng việc setup model, tạo và insert dữ liệu mẫu vào bảng. Và thật may là chúng ta đã setup tất cả mọi thứ từ bài viết trước:

 

View full_post vẫn còn ở kia ! Cool !!!
View full_post vẫn còn ở kia ! Cool !!!

 

Các bạn có thể thấy ở schema public, bên cạnh 3 bảng post, category, author trong mục Tables chúng ta còn có một object khác: một PostgreSQL View có tên full_post trong mục Views. Và hãy để ý trong schema public còn có 1 mục khác nữa: Materialized View. Hiện giờ mục này tạm thời trống rỗng. ;)

OK, mọi thứ đã setup xong, bắt tay vào tạo một Materialized View thôi ! Cú pháp rất đơn giản, rất giống khi tạo View:

 

CREATE MATERIALIZED VIEW full_post_mat_view AS
SELECT post.title, post.content, author.first_name || ' ' || author.last_name AS author_name,
author.email AS author_email, category.title AS category_title, category.description AS category_description
FROM post, category, author
WHERE post.author_id = author.id
AND post.category_id = category.id

 

và đây là kết quả:

 

Hãy nhìn thư mục Materialized Views kìa !!!
Hãy nhìn thư mục Materialized Views kìa !!!

 

Một Materialized View có tên full_post_mat_view đã được tạo ra trong mục Materialized Views. Hãy thử query vào materialized view này xem sao:

 

SELECT *
FROM full_post_mat_view

 

Look cool !!!
Look cool !!!

 

Kết quả thu được giống hệt so với khi query vào View full_post. Vậy là chúng ta đã "đóng gói" thành công câu query vào trong 1 Materialized View và tái sử dụng một cách ngắn gọn, dễ dàng.

Vậy thì, khác biệt lớn nhất giữa Materialized View full_post_mat_view và View full_post là gì ? Hãy cùng tìm hiểu bằng cách INSERT một bản ghi mới vào bảng post:

 

INSERT INTO post (ID, author_id, category_id, title, content) VALUES
(1001, 5, 4, 'So sánh View và Materialized View', 'So sánh View và Materialized View')

 

Sau khi INSERT xong, hãy query vào View full_post để check xem bản ghi mới có xuất hiện trong kết quả trả về không:

 

SELECT *
FROM full_post
WHERE title = 'So sánh View và Materialized View'

 

Bản ghi mới kìa các bạn !!!
Bản ghi mới kìa các bạn !!!

 

Vậy là bản ghi chúng ta vừa INSERT vào đã xuất hiện trong View full_post. Thế còn với Materialized View full_post_mat_view thì sao ? Hãy query thử xem sao:

 

SELECT *
FROM full_post_mat_view
WHERE title = 'So sánh View và Materialized View'

 

Em không tồn tại !!!
Em không tồn tại !!!

 

Vậy là bản ghi chúng ta INSERT vào bảng post không hề tồn tại trong Materialized View full_post_mat_view, khác hoàn toàn so với kết quả query View full_post

Tại thời điểm chúng ta tạo Materialized View full_post_mat_view từ các bảng post, category và authorbảng post lúc đó chỉ có 1000 bản ghi và không hề có bản ghi thứ 1001 với title là 'So sánh View và Materialized View'. full_post_mat_view sau khi được tạo ra sẽ có vai trò giống như 1 bảng gồm các cột:

  • title
  • content
  • author_name
  • author_email
  • category_title
  • category_description

và full_post_mat_view sẽ chỉ lưu trữ kết quả JOIN của 1000 bản ghi bảng post với các bản ghi trong 2 bảng author và category. Bản ghi có ID = 1001 được INSERT vào bảng post sau khi full_post_mat_view được tạo ra, do đó nó sẽ không xuất hiện trong full_post_mat_view. Nói cách khác, chúng ta query trực tiếp vào "bảng" full_post_mat_view chứ không query vào các bảng post, author và category nữa. Ngược lại, với trường hợp query vào View full_post, bản chất chúng ta chỉ thực hiện lại câu lệnh sau đây, có điều theo cách ngắn gọn hơn:

 

SELECT post.title, post.content, author.first_name || ' ' || author.last_name AS author_name,
author.email AS author_email, category.title AS category_title, category.description AS category_description
FROM post, category, author
WHERE post.author_id = author.id
AND post.category_id = category.id

 

Đó chính là câu lệnh góp phần tạo nên View full_post. Điều này có nghĩa là View full_post không hề lưu trữ dữ liệu gì cả, nó không đóng vai trò của một bảng giống như Materialized View full_post_mat_view; khi query vào View full_post, chúng ta vẫn sẽ phải lấy dữ liệu bảng post JOIN với bảng author và category, mà bảng post lúc này đã có thêm 1 bản ghi mới (ID 1001), do đó kết quả trả về sẽ bao gồm cả bản ghi mới mà chúng ta thêm vào.

Nói như vậy thì Materialized View full_post_mat_view sẽ luôn luôn chỉ lưu trữ dữ liệu cũ ? Có cách nào để dữ liệu trong full_post_mat_view cập nhật theo sự thay đổi dữ liệu trong các bảng post, author, category ?

Câu trả lời là: Yes, you can ! Bằng cách sử dụng:

 

REFRESH MATERIALIZED VIEW full_post_mat_view

 

"Làm tươi lại" thành công !!!
"Làm tươi lại" thành công !!!

 

Sau đó, hãy thử query lại:

 

SELECT *
FROM full_post_mat_view
WHERE title = 'So sánh View và Materialized View'

 

À hú ! Nó đây rồi !!!
À hú ! Nó đây rồi !!!

 

Như vậy, với REFRESH MATERIALIZED VIEW, chúng ta có thể cập nhật Materialized View sao cho dữ liệu của nó ăn khớp với dữ liệu của các bảng góp phần tạo nên Materialized View đó.

Túm cái váy lại thì:

  • View giúp lưu trữ câu lệnh, không lưu trữ kết quả của câu lệnh đó. Mỗi lần query vào View là một lần chạy lại câu lệnh
  • Materialized View lưu trữ kết quả của câu lệnh, có vai trò giống như một bảng. Mỗi lần query vào Materialized View có thể coi như là một lần query vào một bảng riêng biệt, không cần phải chạy lại câu lệnh nữa.

Phù !!! Như vậy là chúng ta đã hoàn thành xong series so sánh giữa View và Materialized View trong PostgreSQL. Hẹn gặp lại các bạn trong các bài viết sau nha !

P.S: Thật ra tôi là dân trái ngành, tình cờ đi lạc vào thế giới IT như một trò đùa của số phận =)) Tôi viết bài vừa là để xả stress vừa là để ghi nhớ, tổng hợp lại kiến thức. Mỗi tuần tôi sẽ cố gắng viết 1 bài chia sẻ, tổng hợp lại kiến thức đã học

Bình luận

avatar
Nguyễn Hàn Duy 2020-03-11 01:14:07.921447 +0000 UTC
Thanks ad
Avatar
* Vui lòng trước khi bình luận.
Ảnh đại diện
  0 Thích
0