2011-10-25 19 views
5

Tôi có một truy vấn chạy chậm hơn rất nhiều (~ 5 phút) khi tôi chạy truy vấn đó với mặc định enable_nestloop = true và enable_nestloop = false (~ 10 giây).Postgresql - Truy vấn chạy nhanh hơn rất nhiều với enable_nestloop = false. Tại sao người lập kế hoạch không làm điều đúng?

Giải thích phân tích kết quả cho cả hai trường hợp:

máy A nestloop = true - http://explain.depesz.com/s/nkj0 (~ 5 phút) máy A nestloop = false - http://explain.depesz.com/s/wBM (~ 10 giây)

Trên một máy hơi chậm khác nhau , sao chép cơ sở dữ liệu qua và để mặc định enable_nestloop = true phải mất ~ 20 giây.

Máy B nestloop = true - (~ 20secs)

Đối với tất cả các trường hợp trên, chúng tôi đảm bảo rằng tôi đã làm một PHÂN TÍCH trước khi chạy các truy vấn. Không có truy vấn nào khác chạy song song.

Cả hai máy đang chạy Postgres 8.4. Máy A đang chạy Ubuntu 10.04 32 bit trong khi Máy B đang chạy Ubuntu 8.04 32 bit.

Truy vấn thực tế có sẵn tại đây. Nó là một truy vấn báo cáo với nhiều phép nối khi cơ sở dữ liệu chủ yếu được sử dụng để xử lý giao dịch.

  1. Nếu không sử dụng để đặt thứ gì đó như quan điểm vật chất, tôi có thể làm gì để lập kế hoạch làm những gì tôi đạt được bằng cách đặt enable_nestloop = false?

  2. Từ nghiên cứu tôi đã thực hiện dường như lý do nhà lập kế hoạch chọn truy vấn dường như không tối ưu là do sự khác biệt lớn giữa các hàng ước tính và thực tế. Làm thế nào tôi có thể có được con số này gần hơn?

  3. Nếu tôi nên viết lại truy vấn, tôi nên thay đổi điều gì?

  4. Tại sao trình lập kế hoạch có vẻ như đang làm điều đúng cho Máy B. Tôi nên so sánh gì ở cả hai máy?

+0

Các liên kết từ câu hỏi ở trên đã bị xóa - truy vấn - http://pastie.org/2754424 – Mohan

+0

Giải thích phân tích cho Máy B - http://explain.depesz.com/s/dYO – Mohan

Trả lời

2

Hóa ra truy vấn viết lại là giải pháp tốt nhất. Truy vấn được viết theo cách nó dựa rất nhiều vào các phép nối trái và có nhiều kết nối. Tôi làm phẳng nó ra và giảm sự tham gia trái bằng cách sử dụng kiến ​​thức của tôi về tính chất tham gia của dữ liệu trong các bảng truy vấn được tham gia. Tôi đoán quy tắc của ngón tay cái là nếu người lập kế hoạch sắp ra mắt với ước tính thực sự điên rồ, có thể có cách viết tốt hơn truy vấn.

2

Nếu trình lập kế hoạch truy vấn chọn các kế hoạch truy vấn tối ưu, thì cơ hội có thông tin không đầy đủ hoặc gây hiểu lầm để làm việc.

Xem điều này PostgreSQL Wiki page khi điều chỉnh máy chủ. Đặc biệt chú ý đến các chương trên random_page_costdefault_statistics_target.
Cũng đọc các chương tương ứng trong sách hướng dẫn trên Statistics Used by the PlannerPlanner Cost Constants.

Cụ thể hơn, nó có thể giúp tăng statistics target cho các cột sau:

ALTER TABLE postgres.products ALTER COLUMN id SET STATISTICS 1000; 
ALTER TABLE postgres.sales_orders ALTER COLUMN retailer_id SET STATISTICS 1000; 
ALTER TABLE postgres.sales_orders ALTER COLUMN company_id SET STATISTICS 1000; 

ALTER TABLE goods_return_notes ALTER COLUMN retailer_id SET STATISTICS 1000; 
ALTER TABLE goods_return_notes ALTER COLUMN company_id SET STATISTICS 1000; 

ALTER TABLE retailer_category_leaf_nodes ALTER COLUMN tree_left SET STATISTICS 1000; 
ALTER TABLE channels ALTER COLUMN principal_id SET STATISTICS 1000; 

Đây là tham gia vào các bộ lọc dẫn đến sự khác biệt rất lớn

giữa các hàng ước tính và thực tế.

nhiều hơn. Kiểm tra từng cột nơi người lập kế hoạch lệch rất nhiều so với ước tính. Mặc định chỉ là 100. Chỉ tạo ý nghĩa cho các bảng có >> 1000 hàng. Thử nghiệm với cài đặt. Chạy ANALYZE trên các bảng sau đó để các thay đổi có hiệu lực.

Cũng có thể giúp tạo một chỉ mục một phần trên postgres(sales_orders.retailer_id) WHERE retailer_id IS NOT NULL (tùy thuộc vào giá trị NULL chung).


Một điều mà có thể giúp bạn là để nâng cấp lên phiên bản mới nhất 9.1. Đã có một số cải tiến đáng kể trong lĩnh vực này.

+0

Tôi đánh giá cao thực tế cấu hình có thể tạo sự khác biệt. Tuy nhiên, cấu hình giữa máy A và máy B giống hệt nhau. Bạn có biết bất kỳ thông số loại pg_stats cụ thể nào tôi nên xem không? – Mohan

+0

@Mohan: Tôi đã sửa đổi câu trả lời của mình với các gợi ý cụ thể hơn. –

+0

Cảm ơn Erwin. Chúng tôi đã thử nâng cấp lên 9.1 cũng như đặt random_page_cost thành giá trị thấp hơn - không có kết quả. Tôi sẽ thử các đề xuất khác của bạn. – Mohan

0

Thường chỉ có một lý do cho kế hoạch khác nhau cho cùng một dữ liệu và cùng một truy vấn trên hai máy chủ có cùng PostgreSQL. Đây là cấu hình khác nhau - chủ yếu là giá trị của work_mem. Hash tham gia thường nhanh hơn, nhưng cần rất nhiều bộ nhớ có sẵn.

2

Điều này có thể hữu ích khi đọc: PostgreSQL tutorial about explicit JOINs.

Trình lập kế hoạch truy vấn cố gắng phân tích thứ tự JOIN để tìm thứ tự tốt nhất cho JOINing.

Tôi đã xem Truy vấn của bạn có ít nhất 15 THAM GIA. Số lượng đơn đặt hàng JOIN có thể tăng lên dưới dạng giai thừa (n!). Vì vậy, nó không phải là hợp lý cho kế hoạch truy vấn để cố gắng tìm thứ tự JOIN tốt nhất nếu có 15 JOINs - nó sẽ phải xem xét 15! = 1307674368000 các gói khác nhau.

Vì vậy, nó sử dụng Trình tối ưu hóa truy vấn di truyền thay thế. Xem Query Planning: Genetic Query Optimizer parameters. Tham số "geqo_threshold" xác định số lượng JOIN phải có cho trình hoạch định truy vấn để sử dụng Trình tối ưu hóa truy vấn di truyền.

Bằng cách này, trình lập kế hoạch PostgreSQL chỉ xem xét một phần nhỏ các biến thể có thể và cố gắng tìm một biến thể tốt nhất (ngẫu nhiên). Vì vậy, mỗi lần Bạn chạy ANALYZE, nó có thể đưa ra kế hoạch tốt hơn.

Tôi nghĩ rằng nói chung, nếu bạn có quá nhiều bảng để THAM GIA, Bạn nên làm như bạn đã làm: viết lại truy vấn để tối ưu hóa thứ tự JOIN.

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