2010-02-10 42 views
10

Tôi vừa mới cấu trúc lại cơ sở dữ liệu của mình để sử dụng partitioning trong Postgres 8.2. Bây giờ tôi gặp sự cố với hiệu suất truy vấn:Truy vấn hiệu quả bảng Postgres đa phân vùng

SELECT * 
FROM my_table 
WHERE time_stamp >= '2010-02-10' and time_stamp < '2010-02-11' 
ORDER BY id DESC 
LIMIT 100; 

Có 45 triệu hàng trong bảng. Trước khi phân vùng, thao tác này sẽ sử dụng quét chỉ mục đảo ngược và dừng ngay sau khi đạt đến giới hạn.

Sau khi phân vùng (trên phạm vi thời gian_stamp), Postgres thực hiện quét chỉ mục đầy đủ của bảng chính và phân vùng có liên quan và hợp nhất các kết quả, sắp xếp chúng, sau đó áp dụng giới hạn. Điều này mất quá nhiều thời gian.

tôi có thể sửa chữa nó với:

SELECT * FROM (
    SELECT * 
    FROM my_table_part_a 
    WHERE time_stamp >= '2010-02-10' and time_stamp < '2010-02-11' 
    ORDER BY id DESC 
    LIMIT 100) t 
UNION ALL 
SELECT * FROM (
    SELECT * 
    FROM my_table_part_b 
    WHERE time_stamp >= '2010-02-10' and time_stamp < '2010-02-11' 
    ORDER BY id DESC 
    LIMIT 100) t 
UNION ALL 
    ... and so on ... 
ORDER BY id DESC 
LIMIT 100 

này chạy một cách nhanh chóng. Các phân vùng có dấu thời gian nằm ngoài phạm vi thậm chí không được bao gồm trong kế hoạch truy vấn.

Câu hỏi của tôi là: Có một số gợi ý hoặc cú pháp tôi có thể sử dụng trong Postgres 8.2 để ngăn trình hoạch định truy vấn quét toàn bộ bảng nhưng vẫn sử dụng cú pháp đơn giản chỉ đề cập đến bảng chính không?

Về cơ bản, tôi có thể tránh được nỗi đau khi tự động xây dựng truy vấn UNION lớn trên mỗi phân vùng xảy ra hiện được xác định không?

EDIT: Tôi đã constraint_exclusion kích hoạt (nhờ @ Vinko Vrsalovic)

+1

8.2? có thật không? Trước khi thực hiện bất cứ điều gì khác, bạn nên xem xét nâng cấp lên phiên bản được hỗ trợ (và hiện tại) của Postgres (9.2 là phiên bản hiện tại) –

Trả lời

3

Các bạn đã thử chế trừ (phần 5.9.4 trong tài liệu bạn đã liên kết với)

trừ Hạn chế là truy vấn kỹ thuật tối ưu hóa cải thiện hiệu suất cho các bảng được phân đoạn được xác định theo kiểu được mô tả ở trên. Như một ví dụ:

SET constraint_exclusion = on; 
SELECT count(*) FROM measurement WHERE logdate >= DATE '2006-01-01'; 

Without trừ hạn chế, các truy vấn trên sẽ quét từng phân vùng của bảng đo lường. Khi ràng buộc loại trừ được bật, trình lập kế hoạch sẽ kiểm tra các ràng buộc của mỗi phân vùng và cố gắng chứng minh rằng phân vùng không cần quét bởi vì không thể chứa bất kỳ hàng nào đáp ứng được mệnh đề WHERE của truy vấn. Khi trình lập kế hoạch có thể chứng minh điều này, nó loại trừ phân vùng khỏi kế hoạch truy vấn.

Bạn có thể sử dụng lệnh GIẢI THÍCH để hiển thị sự khác biệt giữa kế hoạch với ràng buộc_kết thúc và lập kế hoạch với nó.

+0

Có, tôi đã bật loại trừ ràng buộc. Thật không may, bảng tổng thể (luôn luôn trống) luôn được bao gồm trong truy vấn vì không thể áp dụng ràng buộc CHECK cho nó (ít nhất là trong 8.2). Điều này có nghĩa là luôn có ít nhất hai bảng liên quan đến truy vấn –

4

Tôi gặp sự cố tương tự mà tôi có thể khắc phục bằng cách truyền điều kiện trong WHERE. EG: (giả sử cột time_stamp là timestamptz loại)

WHERE time_stamp >= '2010-02-10'::timestamptz and time_stamp < '2010-02-11'::timestamptz 

Ngoài ra, hãy chắc chắn rằng các điều kiện CHECK trên bảng được định nghĩa theo cùng một cách ... EG: KIỂM TRA (time_stamp < '2010/02/10' :: timestamptz)

2

tôi đã cùng một vấn đề và nó luộc xuống đến hai lý do trong trường hợp của tôi: Cột

  1. tôi đã lập chỉ mục loại timestamp WITH time zone và hạn chế phân vùng theo cột này với loại timestamp WITHOUT time zone.

  2. Sau khi sửa các ràng buộc ANALYZE của tất cả các bảng con là cần thiết.

Sửa: một chút kiến ​​thức - điều quan trọng là phải nhớ rằng trừ hạn chế (cho phép PG để bỏ qua quét một số bảng dựa trên các tiêu chí phân vùng của bạn) không làm việc với, quote: non-immutable function such as CURRENT_TIMESTAMP

Tôi đã có yêu cầu với CURRENT_DATE và đó là một phần của vấn đề của tôi.

Các vấn đề liên quan