2011-12-15 28 views
5

Tôi có bảng sau:Postgres - Đây có phải là cách thích hợp để tạo chỉ mục một phần trên cột boolean không?

CREATE TABLE recipemetadata 
(
    --Lots of columns 
    diet_glutenfree boolean NOT NULL, 
); 

Hầu hết mỗi hàng sẽ được thiết lập để FALSE trừ khi ai đó đi lên với một số điên gluten mới chế độ ăn uống miễn phí mà càn quét nước.

Tôi cần có khả năng truy vấn rất nhanh các hàng có giá trị này là đúng. Tôi đã tạo chỉ mục:

CREATE INDEX IDX_RecipeMetadata_GlutenFree ON RecipeMetadata(diet_glutenfree) WHERE diet_glutenfree; 

Dường như hoạt động, tuy nhiên tôi không thể biết cách thực sự chỉ lập chỉ mục các hàng có giá trị đúng. Tôi muốn chắc chắn rằng nó không làm điều gì ngớ ngẩn như lập chỉ mục bất kỳ hàng nào có giá trị nào cả.

Tôi có nên thêm toán tử vào mệnh đề WHERE hay cú pháp này hoàn toàn hợp lệ không? Hy vọng rằng đây không phải là một trong những câu hỏi RTFM siêu dễ dàng mà sẽ được giảm xuống 30 lần.

UPDATE:

Tôi đã đi trước và thêm 10.000 hàng để RecipeMetadata với các giá trị ngẫu nhiên. Sau đó tôi đã làm một ANALYZE trên bàn và REINDEX chỉ để chắc chắn. Khi tôi chạy truy vấn:

select recipeid from RecipeMetadata where diet_glutenfree;

tôi nhận được:

'Seq Scan on recipemetadata (cost=0.00..214.26 rows=5010 width=16)' 
' Filter: diet_glutenfree' 

Vì vậy, nó dường như được làm một quét tuần tự trên bàn mặc dù chỉ khoảng một nửa các hàng có cờ này. Chỉ mục đang bị bỏ qua.

Nếu tôi làm:

select recipeid from RecipeMetadata where not diet_glutenfree;

tôi nhận được:

'Seq Scan on recipemetadata (cost=0.00..214.26 rows=5016 width=16)' 
' Filter: (NOT diet_glutenfree)' 

Vì vậy, không có vấn đề gì, chỉ số này không được sử dụng.

+1

Vui lòng thêm liên kết vào danh sách gửi thư PostgreSQL của bạn từ lưu trữ để mọi người có thể kết nối cuộc thảo luận này với tài liệu đó. Nó sẽ được tốt đẹp nếu bạn muốn đăng một theo dõi để gửi bài danh sách gửi thư của bạn với một liên kết đến điều này, quá. Nếu bạn định đăng bài ở nhiều nơi, hãy nói như vậy để ngăn mọi người lặp lại công việc. –

+0

Không vấn đề gì, tôi sẽ làm điều này trong tương lai (Tôi thường không đăng ở cả hai nơi) .. –

+0

BTW, tôi nghĩ câu trả lời ngắn cho câu hỏi của bạn là "Có" ... nhưng nếu bạn lo ngại , điền vào một bảng với một số dữ liệu giả, 'ANALYZE' bảng, sau đó sử dụng' GIẢI THÍCH ANALYZE' để kiểm tra các kế hoạch của một số truy vấn sẽ nhấn chỉ mục một phần. –

Trả lời

4

Tôi đã xác nhận chỉ mục hoạt động như mong đợi.

Tôi đã tạo lại dữ liệu ngẫu nhiên, chỉ thời gian này được đặt diet_glutenfree thành random() > 0.9 vì vậy chỉ có 10% cơ hội là một bit on.

Tôi sau đó tạo lại các chỉ mục và thử lại truy vấn.

SELECT RecipeId from RecipeMetadata where diet_glutenfree; 

Returns:

'Index Scan using idx_recipemetadata_glutenfree on recipemetadata (cost=0.00..135.15 rows=1030 width=16)' 
' Index Cond: (diet_glutenfree = true)' 

Và:

SELECT RecipeId from RecipeMetadata where NOT diet_glutenfree; 

Returns:

'Seq Scan on recipemetadata (cost=0.00..214.26 rows=8996 width=16)' 
' Filter: (NOT diet_glutenfree)' 

Có vẻ như nỗ lực đầu tiên của tôi đã bị ô nhiễm từ PG ước tính nó nhanh hơn để quét toàn bộ bảng thay vì nhấn inde x nếu nó phải tải hơn một nửa các hàng.

Tuy nhiên, tôi nghĩ tôi sẽ nhận được những kết quả chính xác này trên chỉ mục đầy đủ của cột. Có cách nào để xác minh số hàng được lập chỉ mục trong một chỉ mục từng phần không?

CẬP NHẬT

Chỉ số này là khoảng 40k. Tôi tạo ra một chỉ số đầy đủ của cùng một cột và nó trên 200k, do đó, có vẻ như nó chắc chắn là một phần.

+1

Đúng, hãy bật. "Khoảng một nửa" các hàng sẽ không khiến Pg ủng hộ chỉ mục. Bạn sẽ cần nhiều lựa chọn tốt hơn 50% trước khi quét chỉ mục nhanh hơn seqscan. –

+0

Cảm ơn rất nhiều! Tôi cũng đã tạo một chỉ mục đầy đủ để so sánh kích thước. Nó chắc chắn làm việc như mong đợi. –

+0

Lưu ý: bạn dường như chỉ có 10 nghìn bản ghi. 'Bộ làm việc' cho truy vấn của bạn có thể sẽ phù hợp với lõi. Tối ưu hóa bạn thực hiện là tối ưu hóa về mặt sử dụng CPU. Khi "bộ làm việc" lớn hơn dung lượng bộ đệm sẵn có, truy vấn của bạn sẽ trở thành I/O bị ràng buộc và chỉ mục sẽ không giúp bạn nữa (trừ khi các hàng của bạn quá lớn mà chỉ có một số ít phù hợp trên một trang đĩa). – wildplasser

1

Chỉ mục trên trường một bit không có ý nghĩa. Để hiểu được các quyết định của kế hoạch, bạn phải suy nghĩ về mặt trang, không phải về mặt hàng.

Đối với các trang 8K và một hàng (được đánh số) là 80, có 100 hàng trên mỗi trang. Giả sử phân phối ngẫu nhiên, khả năng một trang chỉ bao gồm các hàng có giá trị true là không thể bỏ qua, pow (0.5, 100), khoảng 1e-33, IICC. (và tương tự cho 'false' tất nhiên) Vì vậy, đối với một truy vấn trên gluten_free == true, mỗi trang phải được tìm nạp và lọc sau đó. Việc sử dụng chỉ mục sẽ chỉ gây ra nhiều hơn trang (: chỉ mục) cần tìm nạp.

+1

"Chỉ mục trên trường một bit không có ý nghĩa". Postgres bools yêu cầu 8 bit lưu trữ: http://www.postgresql.org/docs/8.4/static/datatype-boolean.html "Giả sử phân phối ngẫu nhiên" - đây có thể là một giả định lớn. Ít hơn 50% thức ăn thường không chứa gluten. Phản hồi sâu sắc, bất kể. –

+0

"trường một bit" là về nội dung thông tin, không phải về kích thước bộ nhớ được yêu cầu.Có thể có một cấu trúc lưu trữ có thể lưu trữ/lập chỉ mục/truy xuất bitfields một cách hiệu quả (nghĩ: judy-trees) có thể cần ít trang đĩa hơn, nhưng sẽ khó kết hợp chúng với các yêu cầu của ATOM đối với RDBMS. – wildplasser

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