Cho phép người dùng truy cập phân tích dữ liệu theo thời gian thực là khả năng chính của nhiều ứng dụng hiện đại. Hãy tưởng tượng bạn đang sử dụng nền tảng SaaS yêu thích của mình—có thể có một bảng điều khiển trực quan trình bày dữ liệu thời gian thực và thông tin chuyên sâu về lịch sử. Bạn có thể tương tác với nền tảng, tạo báo cáo tùy chỉnh, khám phá các số liệu chi tiết và hình dung các xu hướng kéo dài hàng tuần hoặc hàng tháng.
Bạn chắc chắn sẽ không muốn nền tảng này bị chậm với tư cách là người dùng. Điều này có nghĩa là cơ sở dữ liệu hỗ trợ các sản phẩm này phải chạy nhanh các truy vấn trên khối lượng dữ liệu lớn, bao gồm các truy vấn phân tích, phức tạp.
Trong khi
Dựa trên kỹ thuật cụ thể hóa, các khung nhìn cụ thể hóa của PostgreSQL tính toán trước các truy vấn thường chạy và lưu trữ kết quả dưới dạng bảng. Không giống như các chế độ xem PostgreSQL tiêu chuẩn, chạy truy vấn cơ bản mỗi khi chế độ xem được tham chiếu, các chế độ xem cụ thể hóa vẫn duy trì kết quả của truy vấn nguồn trong cơ sở dữ liệu. Điều tuyệt vời ở đây là cơ sở dữ liệu của bạn không phải thực thi truy vấn mỗi khi bạn chạy: kết quả đã có sẵn trên đĩa—bạn sẽ nhận được phản hồi cho truy vấn của mình nhanh hơn nhiều.
Đây là một cách tuyệt vời để tối ưu hóa phản hồi truy vấn cho các truy vấn sử dụng nhiều tài nguyên để tính toán. Ví dụ: các truy vấn có thể liên quan đến việc xử lý khối lượng lớn dữ liệu, tập hợp hoặc nhiều kết nối.
Làm việc với các chế độ xem cụ thể hóa cực kỳ đơn giản. Để tạo chế độ xem, bạn sẽ sử dụng câu lệnh CREATE MATERIALIZED VIEW
và truy vấn bạn chọn.
Khi chế độ xem cụ thể hóa của bạn được tạo, bạn có thể truy vấn nó dưới dạng bảng PostgreSQL thông thường:
CREATE MATERIALIZED VIEW customer_orders AS SELECT customer_id, COUNT(*) as total_orders FROM orders GROUP BY customer_id;
-- Query the materialized view SELECT * FROM customer_orders;
Chế độ xem cụ thể hóa này sẽ nhanh chóng trở nên cũ kỹ cho đến khi bạn làm mới nó: ngay cả khi bạn đang thêm dữ liệu mới vào bảng cơ sở (hoặc cập nhật hay xóa dữ liệu), chế độ xem cụ thể hóa không tự động bao gồm những thay đổi đó; đó là ảnh chụp nhanh tại thời điểm nó được tạo. Để cập nhật chế độ xem cụ thể hóa, bạn cần chạy REFRESH MATERIALIZED VIEW
.
REFRESH MATERIALIZED VIEW customer_orders;
Điểm cuối cùng này (cách xử lý các lần làm mới) là gót chân Achilles của các chế độ xem cụ thể hóa, như chúng ta sẽ thảo luận trong phần tiếp theo.
Như chúng tôi đã nói, các chế độ xem được cụ thể hóa của PostgreSQL là một công cụ mạnh mẽ để tăng tốc các truy vấn chạy thường xuyên, đặc biệt nếu các truy vấn này xử lý khối lượng dữ liệu lớn. Nhưng các chế độ xem cụ thể hóa đi kèm với một khía cạnh kém lý tưởng hơn: để giữ cho các chế độ xem cụ thể hóa của bạn luôn cập nhật, chúng phải được làm mới.
Vấn đề duy nhất này tạo ra ba hạn chế quan trọng:
Khi làm mới chế độ xem cụ thể hóa, truy vấn sẽ được tính toán lại trên toàn bộ tập dữ liệu. Tóm lại, khi bạn thực hiện làm mới, dữ liệu cũ đã được cụ thể hóa sẽ bị xóa và sau đó được thay thế bằng dữ liệu mới được cụ thể hóa lại. Thực thi
Như đã đề cập trước đó, các chế độ xem được cụ thể hóa sẽ không tự động kết hợp dữ liệu mới nhất. Chúng phải được làm mới bằng cách chạy REFRESH MATERIALIZED VIEW
. Việc chạy làm mới thủ công trong cài đặt sản xuất là không khả thi: thiết lập thực tế hơn nhiều sẽ là tự động làm mới.
Thật không may, các chế độ xem cụ thể hóa không có chức năng làm mới tự động tích hợp sẵn, do đó, việc tạo lịch làm mới tự động cho các chế độ xem cụ thể hóa trong PostgreSQL yêu cầu một loại công cụ lập lịch nào đó. Điều này có thể được xử lý trong cơ sở dữ liệu bằng tiện ích mở rộng hoặc ngoài cơ sở dữ liệu bằng bộ lập lịch như cron. Tuy nhiên, nó được quản lý vì việc làm mới rất tốn kém và mất nhiều thời gian. Rất dễ rơi vào tình huống bạn không thể làm mới chế độ xem đủ nhanh.
Hậu quả của tính chất tĩnh của các chế độ xem được cụ thể hóa là khi được truy vấn, chúng sẽ bỏ lỡ dữ liệu được thêm hoặc thay đổi kể từ lần làm mới gần đây nhất (ngay cả khi việc làm mới đó diễn ra theo lịch trình). Nếu khoảng thời gian lập lịch của bạn được đặt thành một giờ thì tổng thời gian của bạn sẽ lên tới một giờ cộng với thời gian thực tế để thực hiện cập nhật đã lỗi thời. Tuy nhiên, nhiều ứng dụng ngày nay ngụ ý một luồng dữ liệu liên tục được nhập và thông thường, các ứng dụng này phải cung cấp kết quả cập nhật cho người dùng để đảm bảo họ truy xuất thông tin chính xác khi truy vấn chế độ xem.
Thật đáng tiếc là những quan điểm cụ thể hóa lại bị hạn chế bởi những hạn chế này. Nếu bạn đang xây dựng nền tảng SaaS từ một tập dữ liệu trực tiếp, với dữ liệu mới thường xuyên được đưa vào, các chế độ xem cụ thể hóa có nên bị loại bỏ hoàn toàn không?
Câu trả lời là không. Trong Timescale, chúng tôi đã xây dựng một giải pháp giúp nâng cao hiệu quả các chế độ xem cụ thể hóa để làm cho chúng phù hợp hơn với các ứng dụng hiện đại: tổng hợp liên tục.
Hãy tưởng tượng một thế giới nơi các chế độ xem cụ thể hóa không chỉ là ảnh chụp nhanh tĩnh mà còn được cập nhật linh hoạt và hiệu quả. Bạn sẽ truy cập vào cải tiến hiệu suất truy vấn mà bạn tìm kiếm mà không phải lo lắng về bất kỳ điều gì khác. Chà, có vẻ như chúng tôi đã mô tả sự tổng hợp liên tục của Timescale.
Các tập hợp tổng hợp liên tục (có sẵn cho tất cả các cơ sở dữ liệu PostgreSQL thông qua tiện ích mở rộng TimescaleDB và trong AWS thông qua nền tảng Timescale) là các chế độ xem cụ thể hóa được tăng cường bằng khả năng làm mới tự động, hiệu quả và thành phần thời gian thực. Chúng trông và cảm nhận gần giống hệt như các chế độ xem được cụ thể hóa nhưng cho phép những điều sau:
Việc tạo một tổng hợp liên tục rất giống với việc tạo một chế độ xem cụ thể hóa (và nó cũng có thể được truy vấn dưới dạng bảng PostgreSQL thông thường):
CREATE MATERIALIZED VIEW hourly_sales WITH (timescaledb.continuous) AS SELECT time_bucket(INTERVAL '1 hour', sale_time) as hour, product_id, SUM(units_sold) as total_units_sold FROM sales_data GROUP BY hour, product_id;
Nhưng khác với các chế độ xem được cụ thể hóa, việc tạo chính sách làm mới rất đơn giản. Bạn có thể dễ dàng xác định khoảng thời gian làm mới trong cơ sở dữ liệu, đảm bảo rằng tổng hợp liên tục của bạn được cập nhật tự động và định kỳ.
Ví dụ bên dưới thiết lập chính sách làm mới để cập nhật tổng hợp liên tục cứ sau 30 phút. Tham số end_offset
xác định phạm vi thời gian của dữ liệu được làm mới và schedule_interval
đặt tần suất tổng hợp liên tục sẽ được làm mới:
-- Setting up a refresh policy SELECT add_continuous_aggregate_policy('hourly_sales', end_offset => INTERVAL '1 minute', schedule_interval => INTERVAL '30 minutes');
Khi chính sách làm mới này bắt đầu có hiệu lực, quy trình sẽ hiệu quả hơn nhiều so với khi chúng ta sử dụng một chế độ xem cụ thể hóa đơn giản. Không giống như chạy REFRESH MATERIALIZED VIEW
, khi một tập hợp tổng hợp liên tục được làm mới, Timescale không loại bỏ tất cả dữ liệu cũ và tính toán lại tập hợp đó: công cụ chỉ chạy truy vấn theo khoảng thời gian làm mới gần đây nhất (ví dụ: 30 phút) và thêm nó vào đến sự hiện thực hóa.
Tương tự, UPDATE
và DELETE
được thực hiện trong giai đoạn cuối cùng này sẽ được xác định, tính toán lại đoạn (phân vùng) liên quan đến chúng. (Tổng hợp liên tục được xây dựng trên Timescale's
Tuy nhiên, làm cách nào để tổng hợp liên tục giải quyết được vấn đề xem kết quả cập nhật? Điều gì xảy ra nếu dữ liệu mới được thêm vào sau lần làm mới gần đây nhất và tôi truy vấn tổng hợp liên tục?
Để cho phép chức năng này, chúng tôi đã thêm
Chức năng này chuyển đổi các chế độ xem cụ thể hóa từ ảnh chụp nhanh tĩnh thành thực thể động, đảm bảo rằng dữ liệu được lưu trữ không chỉ là sự phản ánh lịch sử mà còn là sự thể hiện cập nhật của các bộ dữ liệu cơ bản.
Ngay cả khi tất cả điều này nghe có vẻ hay, thì (hy vọng) nó sẽ kết hợp tốt hơn rất nhiều với một ví dụ.
Hãy tưởng tượng một nền tảng được sử dụng bởi các đại lý vận tải và các công ty chia sẻ chuyến đi. Nền tảng này chứa một trang tổng quan trong đó các công ty có thể xem tổng quan về trạng thái đội xe của họ, bao gồm một bảng có trạng thái mới nhất của các số liệu chính và hai hình ảnh trực quan cho biết các số liệu đang hoạt động như thế nào vào ngày cụ thể đó và trong bối cảnh của tuần.
Để hỗ trợ ứng dụng này, trước tiên chúng ta phải có một siêu bảng trong đó dữ liệu về các chuyến đi được chèn liên tục. Hypertable có thể trông giống như thế này:
CREATE TABLE rides ( ride_id SERIAL PRIMARY KEY, vehicle_id INT, start_time TIMESTAMPTZ NOT NULL, end_time TIMESTAMPTZ NOT NULL, distance FLOAT NOT NULL, price_paid FLOAT NOT NULL ); SELECT create_hypertable('rides', 'start_time');
Siêu bảng rất nhanh và có khả năng mở rộng rất cao—bảng này sẽ vẫn hoạt động hiệu quả ngay cả khi nó có hàng tỷ hàng.
Để cung cấp thông tin tổng quan trực tiếp cho bảng, chúng tôi sẽ sử dụng tính năng tổng hợp liên tục để sắp xếp dữ liệu trong 30 phút. Điều này sẽ giữ cho quá trình nhanh chóng và đáp ứng:
-- Create continuous aggregate for live overview CREATE MATERIALIZED VIEW live_dashboard WITH (timescaledb.continuous, timescaledb.materialized_only=false)) AS SELECT vehicle_id, time_bucket(INTERVAL '30 minute', start_time) as minute, COUNT(ride_id) as number_of_rides, AVG(price_paid) as average_price FROM rides GROUP BY vehicle_id, minute;
-- Set up a refresh policy SELECT add_continuous_aggregate_policy('live_dashboard', end_offset => INTERVAL '10 minutes', schedule_interval => INTERVAL '15 minute');
Trong mã trước, tham số end_offset
đảm bảo rằng tập hợp không cố gắng làm mới dữ liệu mới nhất ngay lập tức, cho phép một số thời gian đệm để điều chỉnh bất kỳ độ trễ nào khi dữ liệu đến. Đặt end_offset
thành 10 minutes
có nghĩa là dữ liệu tổng hợp sẽ làm mới dữ liệu cũ ít nhất 10 phút, đảm bảo dữ liệu đó không bỏ lỡ các bản cập nhật do luồng dữ liệu vào có độ trễ nhỏ. Trong trường hợp sử dụng trong thế giới thực, bạn sẽ điều chỉnh giá trị này dựa trên độ trễ trung bình mà bạn quan sát được trong đường dẫn dữ liệu của mình.
Để hỗ trợ khả năng trực quan hóa cung cấp chế độ xem hàng ngày, chúng tôi sẽ tạo một tập hợp tổng hợp liên tục thứ hai. Trong biểu đồ này, dữ liệu được hiển thị theo giờ, vì vậy chúng tôi không cần độ chi tiết theo phút như biểu đồ trước:
-- Create continuous aggregate for daily overview CREATE MATERIALIZED VIEW hourly_metrics WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS SELECT vehicle_id, time_bucket(INTERVAL '1 hour', start_time) as hour, COUNT(ride_id) as number_of_rides, SUM(price_paid) as total_revenue FROM rides WHERE start_time > NOW() - INTERVAL '1 day' GROUP BY vehicle_id, hour;
-- Define refresh policy SELECT add_continuous_aggregate_policy('hourly_metrics', end_offset => INTERVAL '10 minutes', schedule_interval => INTERVAL `1 hour`);
Cuối cùng, để hỗ trợ biểu đồ cung cấp chế độ xem hàng tuần, chúng tôi sẽ tạo thêm một tổng hợp liên tục, lần này tổng hợp dữ liệu theo ngày:
-- Create continuous aggregate to power chart with weekly overview CREATE MATERIALIZED VIEW daily_metrics WITH (timescaledb.continuous, timescaledb.materialized_only=false) AS SELECT vehicle_id, time_bucket(INTERVAL '1 day', start_time) as day, COUNT(ride_id) as number_of_rides, SUM(price_paid) as total_revenue FROM rides WHERE start_time > NOW() - INTERVAL '1 week' GROUP BY vehicle_id, day;
-- Define refresh policy SELECT add_continuous_aggregate_policy('daily_metrics', end_offset => INTERVAL '10 minutes', schedule_interval => INTERVAL '1 day);
Tái bút Để làm cho trải nghiệm xác định tập hợp liên tục hiệu quả hơn nữa,
Ngay cả khi PostgreSQL ban đầu không được xây dựng cho các ứng dụng cần xử lý bộ dữ liệu trực tiếp lớn, hãy đoán xem—những loại khối lượng công việc này hiện có ở khắp mọi nơi. Tuy nhiên, PostgreSQL có các tính năng hỗ trợ thực hiện nhiệm vụ này. Các chế độ xem cụ thể hóa là một trong những chế độ xem mạnh mẽ nhất vì chúng cho phép tính toán trước các kết quả truy vấn và lưu trữ chúng trên đĩa để truy xuất nhanh.
Tuy nhiên, quan điểm cụ thể hóa có ba hạn chế quan trọng. Đầu tiên, việc kích hoạt làm mới rất kém hiệu quả về mặt tính toán. Thứ hai, ngay cả việc thiết lập các lần làm mới tự động này cũng không phải là một quá trình liền mạch. Thứ ba, các chế độ xem cụ thể hóa không hiển thị kết quả cập nhật vì chúng loại trừ dữ liệu đã được thêm hoặc sửa đổi kể từ lần làm mới gần đây nhất.
Những hạn chế này làm cho các quan điểm cụ thể hóa trở thành một giải pháp không thực tế cho nhiều ứng dụng hiện đại. Để giải quyết vấn đề này, chúng tôi đã xây dựng các tập hợp liên tục. Đây là các chế độ xem được cụ thể hóa của PostgreSQL trong đó bạn có thể dễ dàng xác định chính sách làm mới, do đó việc làm mới diễn ra tự động. Những lần làm mới đó cũng tăng dần và do đó hiệu quả hơn nhiều. Cuối cùng, tính năng tổng hợp liên tục cho phép bạn kết hợp dữ liệu đã được cụ thể hóa với dữ liệu thô được thêm và sửa đổi kể từ lần làm mới gần đây nhất, đảm bảo bạn sẽ chỉ nhận được kết quả cập nhật.
Nếu bạn đang chạy PostgreSQL trên phần cứng của mình, bạn có thể truy cập các tập hợp liên tục bằng cách
Viết bởi Carlota Soto và Mat Arye.