`WHERE field IS NULL`로 쿼리를 인덱싱하는 방법은 무엇입니까?


14

필드 ( uploaded_at) 중 하나를로 설정하여 삽입이 많은 테이블이 있습니다 NULL. 그런 다음 주기적 작업은 모든 튜플을 선택하고 WHERE uploaded_at IS NULL처리하고 업데이트 uploaded_at하여 현재 날짜로 설정 합니다.

테이블을 어떻게 인덱싱해야합니까?

나는 다음과 같은 부분 인덱스를 사용해야한다는 것을 이해합니다.

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

또는 그런 것. 항상 인 필드에서 색인을 작성하는 것이 맞다면 혼란 스럽습니다 NULL. 또는 b- 트리 인덱스를 사용하는 것이 올바른 경우. 해시는 더 좋은 아이디어처럼 보이지만 더 이상 사용되지 않으며 스트리밍 핫 스탠바이 복제를 통해 복제되지 않습니다. 모든 조언을 주시면 감사하겠습니다.

나는 다음 지수로 조금 실험했다.

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

쿼리 플래너는 항상 foo_part인덱스를 선택하는 것 같습니다 . explain analyse또한 foo_part색인에 대해 약간 더 나은 결과를 얻습니다.

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

vs

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

답변:


10

이 특별한 경우 실제로 인덱스 된 열은 현재 쿼리와 관련이 없습니다. 열을 선택할 수 있습니다. uploaded_at쓸데없는 것 이외의 것을 고를 것입니다 . 다른 쿼리에 유용 할 수 있고 8 바이트보다 크지 않은 열이 이상적입니다.

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

다른 열에 대한 사용 사례가없는 경우 여전히 쓸모없는 것을 사용하는 것이 가장 uploaded_at좋으므로 인덱스에 대한 추가 유지 관리 비용과 HOT 업데이트에 대한 제한을 도입하지 마십시오. 더:

또는 다른 인덱스 열을 사용하지 않는 경우 상수 를 인덱스 식으로 사용하십시오. 처럼:

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

괄호가 필요합니다. 또한 인덱스를 최소 크기로 유지합니다. 그러나 인덱스 열이 8 바이트보다 크지 않지만 (의 경우 timestamp) 어쨌든 여전히 최소 크기입니다. 관련 :


id예를 들어 직렬 필드 일 수 있습니까?
Kirill Zaitsev

1
@teferi : a serial는 다른 것만 큼 좋습니다. 요점은 실제로 그것을 사용하는 쿼리가 있는지 여부입니다.
Erwin Brandstetter 오전
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.