다음 예를 통해 오해를 설명하려고 노력할 것입니다.
의 기본 사항 을 이해하지 못했습니다 Bitmap Heap Scan Node
. SELECT customerid, username FROM customers WHERE customerid < 1000 AND username <'user100';
계획이 다음과 같은 쿼리를 고려하십시오 .
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)
이 노드에 대한 나의 이해 :
거기 에 설명 bitmap heap scan
된대로 , 읽기 순서대로 테이블 블록을 읽기 때문에 무작위 테이블 액세스 오버 헤드가 발생하지 않습니다 Index Scan
.
Index Scan
완료된 후 PostgreSQL은 불필요하게 heap blocks reads
(또는 hits
핫 캐시가있는 경우) 피하기 위해 행을 최적으로 가져 오는 방법을 모릅니다 . 그래서 그것을 알아 내기 위해 인덱스의 두 비트 맵을 생성하고 수행하여 생성 된 구조 ( Bitmap Index Scan
)를 생성합니다 . 비트 맵이 생성되었으므로 이제 불필요한 순서를 피하면서 순차적으로 테이블을 최적으로 읽을 수 있습니다 .bitmap
BITWISE AND
heap I/O-operations
그것은 많은 질문이 오는 곳입니다.
질문 : 비트 맵이 있습니다. PostgreSQL은 행의 물리적 순서에 대한 비트 맵을 어떻게 알 수 있습니까? 또는 비트 맵을 생성하여 해당 요소를 페이지의 포인터에 쉽게 매핑 할 수 있습니까? 그렇다면 모든 것을 설명하지만 내 추측 일뿐입니다.
그렇다면 우리는 단순히 bitmap heap scan -> bitmap index scan
순차적 스캔과 비슷하지만 테이블의 적절한 부분에 불과 하다고 말할 수 있습니까?
답변
PostgreSQL은 행의 물리적 순서에 대한 비트 맵을 어떻게 알 수 있습니까?
비트 맵은 힙 페이지 당 1 비트입니다. 비트 맵 인덱스 스캔은 인덱스 항목이 가리키는 힙 페이지 주소를 기반으로 비트를 설정합니다.
따라서 비트 맵 힙 스캔을 수행 할 때는 선형 테이블 스캔 만 수행하여 비트 맵을 읽어 특정 페이지에 신경을 써야하는지 여부를 확인합니다.
또는 비트 맵을 생성하여 해당 요소를 페이지의 포인터에 쉽게 매핑 할 수 있습니까?
아니요, 비트 맵은 힙 페이지와 1 : 1에 해당합니다.
나는이에 좀 더 썼다 여기 .
이 문맥에서 “비트 맵”의 의미를 오해 한 것 같습니다.
“101011”과 같은 비트 문자열은 각 힙 페이지 또는 각 인덱스 읽기 또는 기타에 대해 작성됩니다.
전체 비트 맵은 단일 비트 배열 이며 스캔중인 관계에 힙 페이지가있는 비트 수입니다.
모든 항목 0 (거짓)으로 시작하여 첫 번째 인덱스 스캔에서 하나의 비트 맵이 작성됩니다. 검색 조건과 일치하는 색인 항목이 발견 될 때마다 해당 색인 항목이 가리키는 힙 주소가 비트 맵에 대한 오프셋으로 조회되고 해당 비트는 1 (true)로 설정됩니다. 따라서 비트 맵 인덱스 스캔은 힙 페이지를 직접 조회하지 않고 비트 맵에서 해당 비트 위치를 찾습니다.
두 번째 및 추가 비트 맵 인덱스 스캔은 다른 인덱스 및 검색 조건과 동일한 작업을 수행합니다.
그런 다음 각 비트 맵이 서로 AND됩니다. 결과 비트 맵은 각 힙 페이지에 대해 하나의 비트를 가지며, 비트는 모든 개별 비트 맵 인덱스 스캔, 즉 모든 인덱스 스캔에 대해 일치하는 검색 조건에서 참인 경우에만 참입니다. 로드 및 검사를 위해 귀찮게해야하는 유일한 힙 페이지입니다. 각 힙 페이지에 여러 행이 포함될 수 있으므로 각 행을 검사하여 모든 조건과 일치하는지 확인해야합니다. 이것이 “조건 확인”부분입니다.
이 모든 것을 이해해야 할 한 가지 중요한 점은 인덱스 항목의 튜플 주소가 ctid
힙 페이지 번호와 힙 페이지 내 오프셋의 조합 인 행을 가리키는 것입니다. 비트 맵 인덱스 스캔은 오프셋을 무시합니다. 어쨌든 전체 페이지를 확인하고 해당 페이지의 행이 조건과 일치하면 비트를 설정합니다.
그래픽 예
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
+---------------------------------------------+
비트 맵이 만들어지면 비트 AND가 수행됩니다.
+---------------------------------------------+
|100000000001000000010000000000000111100000000| bitmap 1
|000001000001000100010000000001000010000000010| bitmap 2
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|000000000001000000010000000000000010000000000| Combined bitmap
+-----------+-------+--------------+----------+
| | |
v v v
Used to scan the heap only for matching pages:
+---------------------------------------------+
|___________X_______X______________X__________|
+---------------------------------------------+
그런 다음 비트 맵 힙 스캔은 각 페이지의 시작을 찾아 페이지를 읽습니다.
+---------------------------------------------+
|___________X_______X______________X__________|
+---------------------------------------------+
seek------->^seek-->^seek--------->^
| | |
------------------------
only these pages read
페이지 당> 1 개의 행이있을 수 있고 조건과 반드시 일치하는 것은 아니기 때문에 각 읽기 페이지는 조건에 대해 다시 검사됩니다.
답변
PostgreSQL의 비트 맵 스캔에 대한 자세한 설명은 내 블로그 게시물 https://rajeevrastogi.blogspot.in/2018/02/bitmap-scan-in-postgresql.html?showComment=1518410565792#c4647352762092142586 를 참조하십시오
.
비트 맵 스캔에 대한 전반적인 빠른 기능 개요 :
-
비트 맵 힙 스캔은 비트 맵 인덱스 스캔에서 튜플을 요청합니다.
-
비트 맵 인덱스 스캔은 일반적인 인덱스 스캔에서와 거의 동일한 방식으로 조건에 따라 인덱스를 스캔합니다. 그러나 힙 데이터에 해당하는 TID (페이지 번호 및 그 내부의 오프셋으로 구성됨)를 반환하는 대신 비트 맵에 해당 TID를 추가합니다. 간단히 이해하기 위해이 비트 맵에는 모든 페이지의 해시 (페이지 번호를 기준으로 해시)가 포함되어 있고 각 페이지 항목에는 해당 페이지 내의 모든 오프셋 배열이 포함되어 있습니다.
-
그런 다음 비트 맵 힙 스캔은 비트 맵을 읽고 저장된 페이지 번호 및 오프셋에 해당하는 힙 데이터를 가져옵니다. 그런 다음 가시성, 자격 등을 확인하고 이러한 모든 확인 결과에 따라 튜플을 반환합니다.