Là một chỉ số tổng hợp cũng tốt cho các truy vấn trên trường đầu tiên?


86

Hãy nói rằng tôi có một bảng với các lĩnh vực AB. Tôi thực hiện các truy vấn thường xuyên trên A+ B, vì vậy tôi đã tạo một chỉ mục tổng hợp trên (A,B). Các truy vấn chỉ Ađược tối ưu hóa hoàn toàn bởi chỉ số tổng hợp?

Ngoài ra, tôi đã tạo một chỉ mục trên A, nhưng Postgres vẫn chỉ sử dụng chỉ mục tổng hợp cho các truy vấn A. Nếu câu trả lời trước là tích cực, tôi đoán nó không thực sự quan trọng, nhưng tại sao nó lại chọn chỉ số tổng hợp theo mặc định, nếu Achỉ mục duy nhất có sẵn?


Tôi đã cố gắng thiết lập một thử nghiệm nhỏ cho việc này. Tuy nhiên, trong trường hợp của tôi, chỉ mục hai cột chỉ được sử dụng khi tôi bỏ cột đơn, không liên quan đến cái nào được tạo trước. Điều thú vị là nếu tôi tạo chỉ mục hai cột trước, kế hoạch ban đầu đã sử dụng quét heap bitmap. Nếu tôi đã tạo chỉ mục một cột, sau đó chạy truy vấn (quét chỉ mục đã sử dụng) và bỏ chỉ mục mới được tạo, kế hoạch liên quan đến chỉ mục hai cột chuyển sang quét chỉ mục. Xem các bước trên SQLFiddle
dezso

@dezso Thú vị. Chi phí cho mỗi truy vấn ở đâu?
Luciano

Chi phí quét chỉ mục bitmap: 107,98, thời gian thực hiện 43 ms. Chỉ mục quét một cột: chi phí 8,69, hai cột: 43,69. Thời gian thực hiện không khác nhau đáng kể (dao động lớn hơn chênh lệch giữa hai lần).
dezso

@Luciano Bạn có thể hiển thị explain analyzevà văn bản truy vấn không?
Craig Ringer

Câu trả lời:


88

Nó chắc chắn là như vậy. Chúng tôi đã thảo luận rằng rất chi tiết theo câu hỏi liên quan này:

Không gian được phân bổ theo bội số MAXALIGN, thường là 8 byte trên HĐH 64 bit hoặc (ít phổ biến hơn) 4 byte trên HĐH 32 bit. Nếu bạn không chắc chắn, hãy kiểm tra pg_controldata. Nó cũng phụ thuộc vào kiểu dữ liệu của các cột được lập chỉ mục (một số yêu cầu đệm căn chỉnh) và nội dung thực tế.

Một chỉ mục trên, giả sử, hai integercột (mỗi cột 4 byte) thường kết thúc chính xác như một chỉ mục trên chỉ một, trong đó 4 byte khác bị mất để đệm liên kết.

Trong trường hợp như vậy, thực sự không có nhược điểm nào cho trình hoạch định truy vấn sử dụng một chỉ mục trên (a,b)- so với chỉ mục trên (a). Và thường thì tốt hơn cho nhiều truy vấn sử dụng cùng một chỉ mục. Cơ hội cho nó (hoặc một phần của nó) nằm trong bộ đệm (nhanh) tăng lên khi được chia sẻ.

Nếu bạn đã duy trì một chỉ mục trên (a,b), thì sẽ không có ý nghĩa gì khi chỉ tạo một chỉ mục khác (a)- trừ khi nó nhỏ hơn đáng kể . Điều này cũng không đúng đối (b,a)vs (a). Theo liên kết trong dòng đầu tiên để biết thêm về điều đó.

Đến từ hướng ngược lại, khi bạn cần một chỉ mục bổ sung như vậy (a,b), sau đó xem xét bỏ chỉ mục hiện tại vào (a)- nếu có thể. Thường thì không thể vì đó là chỉ số của PK hoặc UNIQUEràng buộc. Vì Postgres 11, bạn có thể thoát khỏi việc chỉ thêm bvào định nghĩa ràng buộc với INCLUDEmệnh đề thay thế. Chi tiết trong hướng dẫn.

Hoặc tạo chỉ mục mới (b,a)thay vào đó để chỉ bao gồm các truy vấn b. Đối với chỉ điều kiện bình đẳng, thứ tự của các biểu thức chỉ mục trong các chỉ mục btree không quan trọng. Nó làm, mặc dù, khi liên quan đến điều kiện phạm vi. Xem:

những nhược điểm tiềm ẩn trong việc bao gồm các cột bổ sung trong một chỉ mục, ngay cả khi điều đó chỉ sử dụng không gian bị mất cho phần đệm căn chỉnh:

  • Bất cứ khi nào cột bổ sung được cập nhật, chỉ mục cũng cần cập nhật, điều này có thể thêm chi phí để viết các hoạt động và tạo thêm chỉ số phình to.
  • Cập nhật HOT (Heap Only Tuple) trên bảng là không thể trong khi bất kỳ cột chỉ mục nào có liên quan.

Thêm thông tin cập nhật HOT:

Cách đo kích thước đối tượng:


1
Bạn có thể mở rộng điều này để nói rằng, nếu tôi có một Chỉ số trên cột A và cần phải thêm một chỉ số tổng hợp (A, B), thì chỉ số A nên được loại bỏ? Nếu việc sử dụng lại một chỉ mục giúp cải thiện hiệu quả bộ nhớ cache và (A, B) tối ưu hóa hoàn toàn, A, thì có vẻ như một chỉ mục bổ sung trên A sẽ lãng phí không gian và có khả năng làm mọi thứ chậm lại
jvans

1
@jvans: Nói chung là đúng - với các ngoại lệ và lựa chọn thay thế đáng chú ý. Tôi đã thêm một đoạn để giải quyết điều đó.
Erwin Brandstetter

2

Theo câu hỏi của bạn, bạn có một bảng có trường A và B. Nếu bạn truy vấn của bạn là:

SELECT * FROM [YOUR TBL]
WHERE A='XXXX'

Trình tối ưu hóa sẽ chọn chỉ mục Tổng hợp để tránh Trích xuất truy cập ngẫu nhiên!


-4

Đó là trong trường hợp nếu bạn chỉ sử dụng đầu tiên trong vị ngữ.

Nó sẽ thực hiện quét nếu bạn sử dụng các cột đầu tiên của khóa tổng hợp và cột không khóa của khóa tổng hợp.

Để lừa nó, bạn chỉ có thể giả các vị từ giả như thế này và sau đó là cột không khóa:

[A, B] là chỉ mục của bạn, [C] - một cột khác

Để sử dụng chỉ mục bạn viết như sau:

SELECT
    A,B,C,D,E
FROM 
    test
WHERE
   A=1
AND
   B=B
AND 
   C=3

... tại sao nó chọn chỉ mục tổng hợp theo mặc định, nếu chỉ mục A duy nhất có sẵn?

Nó sẽ chỉ sử dụng chỉ mục trong trường hợp nếu có một hoặc hai vị từ [A] Hoặc [A], [B]. Nó sẽ không sử dụng nó theo thứ tự [B], [A] hoặc [A], [C]. Để có thể sử dụng chỉ mục với cột bổ sung [C], bạn cần thực thi chỉ mục bằng cách sắp xếp các vị từ như [A], [B] và [C].


2
Chính xác những gì bạn đạt được với B=B? Tôi nghĩ bạn không đạt được gì nên tôi bỏ phiếu mà không có bất kỳ bằng chứng nào mà điều này không bị bỏ qua bởi trình tối ưu hóa
Jack Douglas

2
B=Bcó hiệu quả tương tự như B IS NOT NULL, mà dường như chưa được khám phá. Chắc chắn không cần thiết để sử dụng một chỉ số trên (a,b).
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.