Tôi có một cấu trúc bảng được phân vùng như:
CREATE TABLE measurements (
sensor_id bigint,
tx timestamp,
measurement int
);
CREATE TABLE measurements_201201(
CHECK (tx >= '2012-01-01 00:00:00'::timestamp without time zone
AND tx < ('2012-01-01 00:00:00'::timestamp without time zone + '1 mon'::interval))
)INHERITS (measurements);
CREATE INDEX ON measurements_201201(sensor_id);
CREATE INDEX ON measurements_201201(tx);
CREATE INDEX ON measurements_201201(sensor_id, tx);
....
Và như thế. Mỗi bảng có khoảng 20M hàng.
Nếu tôi truy vấn một mẫu cảm biến và mẫu dấu thời gian trong WHERE
mệnh đề, kế hoạch truy vấn sẽ hiển thị các bảng chính xác được chọn và các chỉ mục đang được sử dụng, ví dụ:
SELECT *
FROM measurements
INNER JOIN sensors TABLESAMPLE BERNOULLI (0.01) USING (sensor_id)
WHERE tx BETWEEN '2015-01-04 05:00' AND '2015-01-04 06:00'
OR tx BETWEEN '2015-02-04 05:00' AND '2015-02-04 06:00'
OR tx BETWEEN '2014-03-05 05:00' AND '2014-04-07 06:00' ;
Tuy nhiên, nếu tôi sử dụng CTE hoặc đặt các giá trị dấu thời gian vào một bảng (không hiển thị, ngay cả với các chỉ mục trên bảng tạm thời).
WITH sensor_sample AS(
SELECT sensor_id, start_ts, end_ts
FROM sensors TABLESAMPLE BERNOULLI (0.01)
CROSS JOIN (VALUES (TIMESTAMP '2015-01-04 05:00', TIMESTAMP '2015-01-04 06:00'),
(TIMESTAMP '2015-02-04 05:00', TIMESTAMP '2015-02-04 06:00'),
(TIMESTAMP '2014-03-05 05:00', '2014-04-07 06:00') ) tstamps(start_ts, end_ts)
)
Một cái gì đó như dưới đây
SET constraint_exclusion = on;
SELECT * FROM measurements
INNER JOIN sensor_sample USING (sensor_id)
WHERE tx BETWEEN start_ts AND end_ts
Thực hiện quét chỉ mục trên mỗi bảng. Việc này vẫn còn tương đối nhanh, nhưng với sự phức tạp của các truy vấn ngày càng tăng, điều này có thể biến thành các lần quét seq, kết quả sẽ rất chậm để truy xuất ~ 40K hàng từ một tập hợp con giới hạn của các bảng được phân đoạn (4-5 trên 50).
Tôi lo ngại rằng một cái gì đó như thế này là vấn đề.
Đối với các biểu thức không tầm thường, bạn phải lặp lại điều kiện nguyên văn ít nhiều trong các truy vấn để làm cho trình hoạch định truy vấn Postgres hiểu nó có thể dựa vào ràng buộc CHECK. Ngay cả khi nó có vẻ dư thừa!
Làm cách nào tôi có thể cải thiện phân vùng và cấu trúc truy vấn để giảm khả năng chạy quét seq trên tất cả dữ liệu của mình?