Quét bất ngờ Seq khi thực hiện truy vấn đối với boolean với giá trị NULL


10

Tôi có một cột cơ sở dữ liệu được gọi là auto_reviewloại cột boolean. Có một chỉ mục cho trường đó, được tạo bằng ORM ActiveRecord.

CREATE INDEX index_table_on_auto_renew ON table USING btree (auto_renew);

Khi tôi truy vấn trường cho giá trị boolean, PG sử dụng chỉ mục như mong đợi.

EXPLAIN for: SELECT "table".* FROM "table"  WHERE "table"."auto_renew" = 'f'
                                          QUERY PLAN
----------------------------------------------------------------------------------------------
 Bitmap Heap Scan on table  (cost=51.65..826.50 rows=28039 width=186)
   Filter: (NOT auto_renew)
   ->  Bitmap Index Scan on index_domains_on_auto_renew  (cost=0.00..44.64 rows=2185 width=0)
         Index Cond: (auto_renew = false)
(4 rows)

Khi giá trị là NULL, quét tuần tự được sử dụng.

EXPLAIN for: SELECT "table".* FROM "table"  WHERE "table"."auto_renew" IS NULL
                           QUERY PLAN
----------------------------------------------------------------
 Seq Scan on table  (cost=0.00..1094.01 rows=25854 width=186)
   Filter: (auto_renew IS NULL)
(2 rows)

Tôi tò mò muốn biết lý do đằng sau sự lựa chọn này.

Câu trả lời:


19

Nói chung, col IS NULLlà một ứng cử viên có thể cho tìm kiếm chỉ mục b-cây (mặc định). Hướng dẫn sử dụng :

Ngoài ra, một IS NULLhoặc IS NOT NULLđiều kiện trên một cột chỉ mục có thể được sử dụng với chỉ mục cây B.

Để có bằng chứng, hãy tắt các lần quét liên tiếp (chỉ trong một phiên kiểm tra!):

SET enable_seqscan = OFF;

Tôi trích dẫn hướng dẫn ở đây :

enable_seqscan (boolean)

Cho phép hoặc vô hiệu hóa việc sử dụng các loại kế hoạch quét tuần tự của trình hoạch định truy vấn. Không thể triệt tiêu hoàn toàn các lần quét liên tiếp, nhưng tắt biến này không khuyến khích người lập kế hoạch sử dụng một phương thức nếu có sẵn các phương pháp khác. Mặc định là bật.

Sau đó thử lại:

EXPLAIN ANALYZE SELECT * FROM tbl WHERE auto_renew IS NULL;

Điều này có thể sẽ dẫn đến việc quét chỉ mục bitmap chậm hơn so với quét tuần tự trên bảng.

Đặt lại hoặc đóng phiên (cài đặt là phiên cục bộ).

RESET enable_seqscan;

Chỉ mục trên booleancác cột chỉ hữu ích trong một số trường hợp nhất định. Công cụ lập kế hoạch chỉ sử dụng một chỉ mục nếu nó hy vọng rằng nó sẽ nhanh hơn. Tính toán dựa trên cài đặt chi phí của bạn và số liệu thống kê được thu thập bởi ANALYZE. Nếu một phần khá lớn của bảng phù hợp với điều kiện của bạn (khoảng 5% trở lên, thì tùy thuộc), thông thường sẽ nhanh hơn để thực hiện quét toàn bộ bảng thay thế.

Điều này để lại giá trị hiếm trong một booleancột là ứng cử viên hữu ích duy nhất cho một chỉ mục đơn giản. Và thông thường sẽ hiệu quả hơn khi tạo một chỉ mục một phần (chuyên biệt hơn) thay vì điều này - rẻ hơn để duy trì, nhỏ hơn, nhanh hơn và được sử dụng dễ dàng hơn nếu điều kiện truy vấn khớp.

Nếu bạn có nhiều truy vấn tìm kiếm các hàng với auto_renew IS NULLNULLtrường hợp không phổ biến lắm (và / hoặc bạn cần một thứ tự sắp xếp nhất định) thì chỉ mục này sẽ giúp tìm / sắp xếp các hàng này một cách nhanh chóng:

CREATE INDEX index_tbl_tbl_id_auto_renew_null ON tbl (tbl_id)
WHERE auto_renew IS NULL;

Điều kiện của chỉ mục một phần phải được lặp lại trong WHEREmệnh đề của truy vấn ít nhiều chính xác để làm cho trình hoạch định truy vấn nhận ra chỉ mục được áp dụng.

Cột được lập chỉ mục ( tbl_id) là một lựa chọn tùy ý. Phần quan trọng là WHEREmệnh đề. Chỉ mục cụ thể này sẽ có hiệu quả nhất đối với các truy vấn có ORDER BY tbl_idhoặc bộ lọc bổ sung hoặc tham gia tbl_id. Bạn có thể làm cho nó một chỉ số nhiều màu . Các cột Boolean thường hữu ích hơn khi kết hợp với các cột khác.

Ngoài ra: ORM là những cái nạng thường không thể phát huy hết tiềm năng ra khỏi RDBMS của bạn.


Câu trả lời tuyệt vời, cảm ơn bạn Erwin. Tôi buồn tôi không thể nâng cấp nó hai lần.
Simone Carletti
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.