Hiểu về heap bitmap quét quét và quét chỉ mục bitmap


36

Tôi sẽ cố gắng giải thích những hiểu lầm của tôi bằng ví dụ sau.

Tôi đã không hiểu các nguyên tắc cơ bản của Bitmap Heap Scan Node. Hãy xem xét các truy vấn SELECT customerid, username FROM customers WHERE customerid < 1000 AND username <'user100';kế hoạch đó là:

Bitmap Heap Scan on customers  (cost=25.76..61.62 rows=10 width=13) (actual time=0.077..0.077 rows=2 loops=1)
  Recheck Cond: (((username)::text < 'user100'::text) AND (customerid < 1000))
  ->  BitmapAnd  (cost=25.76..25.76 rows=10 width=0) (actual time=0.073..0.073 rows=0 loops=1)
        ->  Bitmap Index Scan on ix_cust_username  (cost=0.00..5.75 rows=200 width=0) (actual time=0.006..0.006 rows=2 loops=1)
              Index Cond: ((username)::text < 'user100'::text)
        ->  Bitmap Index Scan on customers_pkey  (cost=0.00..19.75 rows=1000 width=0) (actual time=0.065..0.065 rows=999 loops=1)
              Index Cond: (customerid < 1000)

Sự hiểu biết của tôi về nút này :

Như đã giải thích ở đó , các bitmap heap scankhối bảng đọc theo thứ tự tuần tự, do đó nó không tạo ra chi phí truy cập bảng ngẫu nhiên, điều này xảy ra như đang làm Index Scan.

Sau khi Index Scanhoàn thành, PostgreSQL không biết cách tìm nạp các hàng một cách tối ưu, để tránh không cần thiết heap blocks reads(hoặc hitsnếu có bộ đệm nóng). Vì vậy, để tìm ra nó, nó tạo ra cấu trúc ( Bitmap Index Scan) được gọi là bitmaptrong trường hợp của tôi đang được tạo bằng cách tạo hai bitmap của các chỉ mục và thực hiện BITWISE AND. Vì bitmap đã được tạo nên giờ đây nó có thể đọc bảng một cách tối ưu theo thứ tự liên tục, tránh không cần thiết heap I/O-operations.

Đó là nơi có rất nhiều câu hỏi.

HỎI: Chúng tôi chỉ có một bitmap. Làm thế nào để PostgreSQL biết chỉ bằng một bitmap bất cứ thứ gì về thứ tự vật lý của hàng? Hoặc tạo bitmap để bất kỳ phần tử nào của nó có thể được ánh xạ tới con trỏ tới một trang dễ dàng? Nếu vậy, điều đó giải thích mọi thứ, nhưng đó chỉ là phỏng đoán của tôi.

Vì vậy, chúng ta có thể nói đơn giản rằng bitmap heap scan -> bitmap index scannó giống như một lần quét liên tiếp nhưng chỉ là phần thích hợp của bảng không?


Tôi đã viết một lời giải thích về một số điều này ở đây: stackoverflow.com/q/33100637/398670
Craig Ringer

@CraigRinger Có vẻ như tôi đã không giải thích chính xác những gì tôi không hiểu. Tất nhiên, như bạn đã giải thích, chúng tôi có một bitmap mà PostgreSQL đọc bảng tuần tự. Tôi không hiểu làm thế nào nó có thể tìm ra khối thực tế được chỉ định bởi một bitmap cụ thể, vd 001001010101011010101. Hoặc nó thực sự không quan trọng và tất cả những gì chúng ta phải biết chỉ là nó có thể tìm thấy một khối bằng bitmap theo cách khá nhanh ...?
St.Antario

Ah, bạn có thể hiểu nhầm "bitmap" nghĩa là gì ở đây. Hãy để tôi theo dõi trong một chỉnh sửa.
Craig Ringer

@CraigRinger Có lẽ, tôi đã nhận định từ đó .
St.Antario

Câu trả lời:


52

Làm thế nào để PostgreSQL biết chỉ bằng một bitmap bất cứ thứ gì về thứ tự vật lý của hàng?

Bitmap là một bit trên mỗi trang heap. Quét chỉ mục bitmap đặt các bit dựa trên địa chỉ trang heap mà mục nhập chỉ mục trỏ tới.

Vì vậy, khi thực hiện quét heap bitmap, nó chỉ thực hiện quét bảng tuyến tính, đọc bitmap để xem liệu nó có nên làm phiền với một trang cụ thể hay tìm kiếm trên đó.

Hoặc tạo bitmap để bất kỳ phần tử nào của nó có thể được ánh xạ tới con trỏ tới một trang dễ dàng?

Không, bitmap tương ứng 1: 1 cho các trang heap.

Tôi đã viết thêm một số về điều này ở đây .


OK, có vẻ như bạn có thể đang hiểu nhầm "bitmap" nghĩa là gì trong bối cảnh này.

Đó không phải là một chuỗi bit như "101011" được tạo cho mỗi trang heap, hoặc mỗi chỉ mục đọc, hoặc bất cứ điều gì.

Toàn bộ bitmap là một mảng bit đơn , có nhiều bit như có các trang heap trong mối quan hệ đang được quét.

Một bitmap được tạo bởi lần quét chỉ mục đầu tiên, bắt đầu với tất cả các mục 0 (sai). Bất cứ khi nào một mục nhập chỉ mục phù hợp với điều kiện tìm kiếm được tìm thấy, địa chỉ heap được chỉ ra bởi mục nhập chỉ mục đó được tìm kiếm như một phần bù vào bitmap và bit đó được đặt thành 1 (true). Vì vậy, thay vì tìm kiếm trang heap trực tiếp, quét chỉ mục bitmap tìm kiếm vị trí bit tương ứng trong bitmap.

Quét chỉ mục bitmap thứ hai và xa hơn làm điều tương tự với các chỉ mục khác và các điều kiện tìm kiếm trên chúng.

Sau đó, mỗi bitmap được ANDed với nhau. Bitmap kết quả có một bit cho mỗi trang heap, trong đó các bit chỉ đúng nếu chúng đúng trong tất cả các lần quét chỉ mục bitmap riêng lẻ, tức là điều kiện tìm kiếm phù hợp với mỗi lần quét chỉ mục. Đây là những trang heap duy nhất chúng ta cần bận tâm để tải và kiểm tra. Vì mỗi trang heap có thể chứa nhiều hàng, sau đó chúng tôi phải kiểm tra từng hàng để xem nó có phù hợp với tất cả các điều kiện hay không - đó là phần "kiểm tra lại".

Một điều rất quan trọng để hiểu với tất cả điều này là địa chỉ bộ dữ liệu trong mục nhập chỉ mục trỏ đến hàng ctid, là sự kết hợp của số trang heap và phần bù trong trang heap. Quét chỉ mục bitmap bỏ qua các offset, vì dù sao nó cũng sẽ kiểm tra toàn bộ trang và đặt bit nếu bất kỳ hàng nào trên trang đó khớp với điều kiện.


Ví dụ đồ họa

Heap, one square = one page:
+---------------------------------------------+
|c____u_____X___u___X_________u___cXcc______u_|
+---------------------------------------------+
Rows marked c match customers pkey condition.
Rows marked u match username condition.
Rows marked X match both conditions.


Bitmap scan from customers_pkey:
+---------------------------------------------+
|100000000001000000010000000000000111100000000| bitmap 1
+---------------------------------------------+
One bit per heap page, in the same order as the heap
Bits 1 when condition matches, 0 if not

Bitmap scan from ix_cust_username:
+---------------------------------------------+
|000001000001000100010000000001000010000000010| bitmap 2
+---------------------------------------------+

Khi bitmap được tạo một bit VÀ được thực hiện trên chúng:

+---------------------------------------------+
|100000000001000000010000000000000111100000000| bitmap 1
|000001000001000100010000000001000010000000010| bitmap 2
 &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|000000000001000000010000000000000010000000000| Combined bitmap
+-----------+-------+--------------+----------+
            |       |              |
            v       v              v
Used to scan the heap only for matching pages:
+---------------------------------------------+
|___________X_______X______________X__________|
+---------------------------------------------+

Quét heap bitmap sau đó tìm đến đầu mỗi trang và đọc trang:

+---------------------------------------------+
|___________X_______X______________X__________|
+---------------------------------------------+
seek------->^seek-->^seek--------->^
            |       |              |
            ------------------------
            only these pages read

và mỗi trang đọc sau đó được kiểm tra lại theo điều kiện vì có thể có> 1 hàng trên mỗi trang và không nhất thiết phải phù hợp với điều kiện.


Ah, đó là những gì họ có nghĩa là bởi Populating bitmap.
St.Antario

@ St.Antario Tôi đã thêm đồ họa để giải thích
Craig Ringer

Hãy để tôi làm rõ một điều nữa về quét bitmap. Bạn nói rằng chúng ta có một bitmap 1: 1 để heap các trang và chúng ta có thể xác định một trang heap bằng một chỉ mục bit trong bitmap. Vì mối quan hệ có thể chứa các trang trên đĩa theo thứ tự không tuần tự (không được phân cụm) nên chúng tôi không thể xác định địa chỉ của trang bằng cách chỉ bù vào bitmap. Tôi đoán, người lập kế hoạch biết cách tính địa chỉ trang bằng cách bù cho một mối quan hệ nhất định . Điều đó có đúng không?
St.Antario 30/03/2016

1
Vì vậy, chúng tôi phải đặt tất cả các trang trên một ổ đĩa. Ngoài ra, dữ liệu của mối quan hệ có thể được trải đều trên hai hoặc nhiều ổ đĩa (do đó khó có thể tưởng tượng bất kỳ thứ tự tuyến tính nào của các trang quan hệ ), vì vậy việc xác định độ lệch thực tế của trang tiếp theo là khó khăn. Bởi vì tôi tin rằng bằng cách "bù", bạn có nghĩa là bù vật lý thực tế tương ứng với vị trí vật lý trên ổ đĩa.
St.Antario 30/03/2016

2
PostgreSQL không quan tâm một chút về các ổ đĩa. Nó chỉ quan tâm đến các tập tin trên hệ thống tập tin . Tệp logic cho mối quan hệ là tuyến tính và liền kề, và đó là những gì bitmap đã kết thúc. (Có thể có nhiều phạm vi cho tệp, nhưng chúng được xử lý như thể chúng được nối liên tục và bitmap vượt qua tất cả chúng). Bạn đang nhìn vào mức độ trừu tượng sai. (Một lưu ý phụ, bitmap trong quét chỉ mục bitmap cũng không được tính toán bởi trình hoạch định, đó là một phần của phương thức truy cập chỉ mục btree và liên quan nhiều hơn đến người thực thi hơn là trình hoạch định).
Craig Ringer

3

Vui lòng tham khảo bài đăng trên blog của tôi https://rajeevrastogi.blogspot.in/2018/02/bitmap-scan-in-postgresql.html?showVer=1518410565792#c4647352762092142586 để biết chi tiết mô tả về quét bitmap trong PostgreQuery.

Tổng quan về chức năng tổng thể nhanh chóng của quét bitmap:

  1. Quét bitmap Heap yêu cầu một tuple từ Bitmap Index Scan.

  2. Bitmap Index Scan quét chỉ mục theo điều kiện gần như giống như cách thực hiện trong Quét chỉ mục thông thường. Nhưng thay vì trả về TID (bao gồm trang no và offset trong đó) tương ứng với dữ liệu heap, nó thêm TID đó vào một bitmap. Để hiểu đơn giản, bạn có thể xem xét bitmap này chứa hàm băm của tất cả các trang (được băm dựa trên trang số) và mỗi mục nhập trang chứa mảng của tất cả phần bù trong trang đó.

  3. Sau đó, Bitmap Heap Scan đọc qua bitmap để lấy dữ liệu heap tương ứng với số trang được lưu trữ và offset. Sau đó, nó kiểm tra khả năng hiển thị, trình độ vv và trả về bộ dữ liệu dựa trên kết quả của tất cả các kiểm tra này.

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.