Làm cách nào để lập chỉ mục một truy vấn với `WHERE trường IS NULL`?


13

Tôi có một bảng có nhiều phần chèn, đặt một trong các trường ( uploaded_at) thành NULL. Sau đó, một tác vụ định kỳ chọn tất cả các bộ dữ liệu WHERE uploaded_at IS NULL, xử lý chúng và cập nhật, thiết lập uploaded_atcho đến ngày hiện tại.

Làm thế nào tôi nên lập chỉ mục bảng?

Tôi hiểu rằng tôi nên sử dụng một chỉ mục một phần như:

CREATE INDEX foo ON table (uploaded_at) WHERE uploaded_at IS NULL

Hoặc smth như thế. Tôi hơi bối rối mặc dù nó là chính xác để lập chỉ mục trên một lĩnh vực luôn luôn NULL. Hoặc nếu nó là chính xác để sử dụng một chỉ số b-cây. Hash có vẻ như là một ý tưởng tốt hơn, nhưng nó đã lỗi thời và không được sao chép thông qua việc sao chép dự phòng nóng. Bất kỳ lời khuyên sẽ được đánh giá rất cao.

Tôi đã thử nghiệm một chút với các chỉ số sau:

"foo_part" btree (uploaded_at) WHERE uploaded_at IS NULL
"foo_part_id" btree (id) WHERE uploaded_at IS NULL

và trình hoạch định truy vấn dường như luôn chọn foo_partchỉ mục. explain analysecũng mang lại kết quả tốt hơn một chút cho foo_partchỉ số:

Index Scan using foo_part on t1  (cost=0.28..297.25 rows=4433 width=16) (actual time=0.025..3.649 rows=4351 loops=1)
   Index Cond: (uploaded_at IS NULL)
 Total runtime: 4.060 ms

đấu với

Bitmap Heap Scan on t1  (cost=79.15..6722.83 rows=4433 width=16) (actual time=1.032..4.717 rows=4351 loops=1)
   Recheck Cond: (uploaded_at IS NULL)
   ->  Bitmap Index Scan on foo_part_id  (cost=0.00..78.04 rows=4433 width=0) (actual time=0.649..0.649 rows=4351 loops=1)
 Total runtime: 5.131 ms

Câu trả lời:


10

Trong trường hợp đặc biệt này, cột thực sự được lập chỉ mục là không liên quan cho truy vấn có sẵn. Bạn có thể chọn bất kỳ cột. Tôi sẽ chọn một cái gì đó khác hơn uploaded_at, đó là vô dụng. Một số cột có thể hữu ích cho các truy vấn khác và không lớn hơn 8 byte, lý tưởng nhất.

CREATE INDEX foo ON table bar (some_col) WHERE uploaded_at IS NULL;

Nếu bạn không có trường hợp sử dụng cho bất kỳ cột nào khác, tốt nhất vẫn nên gắn bó với vô dụng uploaded_at, vì vậy không nên đưa ra chi phí bảo trì bổ sung cho chỉ mục và các hạn chế đối với các cập nhật NÓNG. Hơn:

Hoặc sử dụng hằng số dưới dạng biểu thức chỉ mục nếu bạn không sử dụng cho bất kỳ cột chỉ mục nào khác. Giống:

CREATE INDEX baz ON table bar ((TRUE)) WHERE uploaded_at IS NULL;

Yêu cầu dấu ngoặc đơn. Điều này cũng giữ cho chỉ số ở kích thước tối thiểu. Nhưng trong khi cột chỉ mục không bao giờ lớn hơn 8 byte (đó là trường hợp timestamp), dù sao thì nó vẫn ở kích thước tối thiểu. Liên quan:


Nó có thể là một idlĩnh vực nối tiếp chẳng hạn?
Kirill Zaitsev

1
@teferi: a seriallà tốt như bất kỳ. Vấn đề là liệu có thực sự có các truy vấn để sử dụng nó hay không.
Erwin Brandstetter
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.