2008-11-21 30 views

Trả lời

60

Giả sử bạn đang hỏi về tính năng "gợi ý chỉ mục" phổ biến được tìm thấy trong nhiều cơ sở dữ liệu, PostgreSQL không cung cấp tính năng như vậy. Đây là một quyết định có ý thức của nhóm PostgreSQL. Một tổng quan tốt về lý do tại sao và những gì bạn có thể làm thay vào đó có thể được tìm thấy here. Lý do cơ bản là nó là một hack hiệu suất có xu hướng gây ra nhiều vấn đề hơn sau khi dòng dữ liệu của bạn thay đổi, trong khi trình tối ưu hóa của PostgreSQL có thể đánh giá lại kế hoạch dựa trên thống kê. Nói cách khác, những gì có thể là một kế hoạch truy vấn tốt ngày hôm nay có lẽ sẽ không phải là một kế hoạch truy vấn tốt cho tất cả các thời gian, và gợi ý chỉ mục buộc một kế hoạch truy vấn cụ thể cho mọi thời đại.

Là một cái búa rất cùn, hữu ích để thử nghiệm, bạn có thể sử dụng các tham số enable_seqscanenable_indexscan. Xem:

Đây là những không thích hợp cho liên tục sử dụng sản xuất. Nếu bạn gặp sự cố với lựa chọn gói truy vấn, bạn sẽ thấy the documentation for tracking down query performance issues. Không chỉ đặt enable_ thông số và đi bộ.

Trừ khi bạn có lý do rất tốt để sử dụng chỉ mục, Postgres có thể đưa ra lựa chọn đúng. Tại sao?

  • Đối với các bảng nhỏ, việc quét tuần tự sẽ nhanh hơn.
  • Postgres không sử dụng các chỉ mục khi các kiểu dữ liệu không khớp đúng cách, bạn có thể cần phải bao gồm các phôi phù hợp.
  • Cài đặt kế hoạch của bạn có thể gây ra sự cố.

Xem thêm this old newsgroup post.

+4

Đồng ý, Buộc postgres để làm điều đó theo cách của bạn thường có nghĩa là bạn đã làm sai rồi. 9/10 Times, người lập kế hoạch sẽ đánh bại bất cứ thứ gì bạn có thể nghĩ ra. Một thời gian khác của nó bởi vì bạn đã làm cho nó sai. –

+0

Tôi nghĩ rằng đó là một ý tưởng tốt để kiểm tra các lớp vận hành thực sự của việc giữ chỉ mục của bạn. – metdos

+2

Tôi ghét phải hồi sinh một câu hỏi cũ nhưng tôi thường thấy trong tài liệu, thảo luận và ở đây, nhưng có khái niệm khái quát về những gì đủ điều kiện cho * bảng nhỏ * không? Có giống 5000 hàng hay 50000 không? – waffl

0

Sản phẩm máy chủ nâng cao của PostgresPlus EnterpriseDB hỗ trợ cú pháp gợi ý Oracle, mặc dù sản phẩm đó không phải là miễn phí.

9

Câu hỏi trên chính nó là rất nhiều không hợp lệ. Buộc (bằng cách làm enable_seqscan = off ví dụ) là ý tưởng rất xấu. Nó có thể hữu ích để kiểm tra xem nó sẽ được nhanh hơn, nhưng mã sản xuất không bao giờ nên sử dụng thủ thuật như vậy.

Thay vào đó - hãy giải thích phân tích truy vấn của bạn, đọc nó và tìm hiểu lý do tại sao PostgreSQL chọn gói xấu (theo ý kiến ​​của bạn).

Có các công cụ trên web giúp đọc giải thích kết quả phân tích - một trong số đó là explain.depesz.com - được viết bởi tôi.

Tùy chọn khác là tham gia kênh #postgresql trên freenode mạng irc và trò chuyện với những người ở đó để giúp bạn - vì tối ưu hóa truy vấn không phải là vấn đề "đặt câu hỏi, nhận câu trả lời vui". nó giống như một cuộc trò chuyện, với nhiều điều cần kiểm tra, nhiều điều cần học.

+0

Danh sách gửi thư cũng là một nơi tuyệt vời để nhận trợ giúp. – jpmc26

44

Có lẽ lý do chính đáng duy nhất cho việc sử dụng

set enable_seqscan=false 

là khi bạn đang viết các truy vấn và muốn nhanh chóng xem những gì kế hoạch truy vấn thực sự sẽ có một lượng lớn dữ liệu trong bảng (s). Hoặc tất nhiên nếu bạn cần nhanh chóng xác nhận rằng truy vấn của bạn không sử dụng chỉ mục đơn giản vì tập dữ liệu quá nhỏ.

+36

trả lời ngắn này thực sự đưa ra một gợi ý tốt cho mục đích thử nghiệm – dwery

+2

Không ai trả lời câu hỏi! –

+0

@IvailoBardarov Lý do tất cả các đề xuất khác đều ở đây là vì PostgreSQL không có tính năng này; đây là một quyết định có ý thức của các nhà phát triển dựa trên cách nó thường được sử dụng và các vấn đề lâu dài mà nó gây ra. – jpmc26

7

Đôi khi PostgreSQL không thực hiện lựa chọn chỉ mục tốt nhất cho một điều kiện cụ thể. Ví dụ, giả sử có một bảng giao dịch với vài triệu hàng, trong đó có hàng trăm hàng cho bất kỳ ngày cụ thể nào và bảng có bốn chỉ mục: transaction_id, client_id, date và description. Bạn muốn chạy các truy vấn sau đây:

SELECT client_id, SUM(amount) 
FROM transactions 
WHERE date >= 'yesterday'::timestamp AND date < 'today'::timestamp AND 
     description = 'Refund' 
GROUP BY client_id 

PostgreSQL có thể chọn để sử dụng transactions_description_idx chỉ số thay vì transactions_date_idx, có thể dẫn đến các truy vấn lấy vài phút thay vì ít hơn một giây. Nếu đây là trường hợp, bạn có thể buộc bằng cách sử dụng chỉ mục trên cập nhật bằng cách fudging điều kiện như thế này:

SELECT client_id, SUM(amount) 
FROM transactions 
WHERE date >= 'yesterday'::timestamp AND date < 'today'::timestamp AND 
     description||'' = 'Refund' 
GROUP BY client_id 
0

Có một đánh dấu để đẩy postgres để thích một seqscan thêm một OFFSET 0 trong subquery

này rất tiện lợi cho việc tối ưu hóa các yêu cầu liên kết các bảng lớn/lớn khi bạn đang thực sự chỉ tìm kiếm nắm tay n/phần tử cuối cùng.

Giả sử bạn đang tìm kiếm 20 phần tử đầu tiên/cuối cùng liên quan đến nhiều bảng có mục nhập 100k (hoặc nhiều hơn), không xây dựng điểm/liên kết tất cả truy vấn trên tất cả dữ liệu khi bạn đang tìm kiếm 100 hoặc 1000 mục đầu tiên. Trong trường hợp này, ví dụ, nó quay nhanh hơn 10 lần để thực hiện quét tuần tự.

thấy How can I prevent Postgres from inlining a subquery?

Các vấn đề liên quan