2008-09-22 27 views
85

Kết quả giải thích của MySQL khá đơn giản. PostgreSQL phức tạp hơn một chút. Tôi đã không thể tìm thấy một nguồn tài nguyên tốt mà giải thích nó.PostgreSQL giải thích cho tôi biết chính xác điều gì?

Bạn có thể mô tả chính xác những gì giải thích đang nói hoặc ít nhất là chỉ cho tôi theo hướng của một nguồn lực tốt không?

Trả lời

47

Explaining_EXPLAIN.pdf cũng có thể giúp ích.

+28

Tôi băn khoăn tại sao mọi người nghĩ rằng trang trình bày làm cho tài liệu kỹ thuật tốt. Video của cuộc nói chuyện có thể hữu ích, nhưng mật độ thông tin của bản chiếu đó rất gần bằng không. Trong sáu slide đầu tiên (1/5 của tổng số), có chính xác 1 câu nội dung kỹ thuật: "• GIẢI THÍCH làm việc trên bất kỳ DML không chỉ SELECT (tức là UPDATE, DELETE, và INSERT)". Sự hiểu lầm lớn nhất của tôi là những gì "khởi động" thời gian có nghĩa là, và đó là không giải thích bất cứ nơi nào trong ~ 30 slide. –

36

Nó thực thi từ hầu hết thụt lề để thụt lề ít nhất, và tôi tin từ đáy của kế hoạch lên đỉnh. (Vì vậy, nếu có hai phần thụt lề, thì một phần ở phía dưới trang sẽ thực hiện trước, sau đó khi chúng gặp nhau, thì quy tắc kết hợp chúng sẽ thực hiện.)

Ý tưởng là ở mỗi bước có 1 hoặc 2 bộ dữ liệu đến và được xử lý bởi một số quy tắc. Nếu chỉ một tập dữ liệu, hoạt động đó được thực hiện cho tập dữ liệu đó. (Ví dụ quét một chỉ mục để tìm ra những hàng bạn muốn, lọc một tập dữ liệu hoặc sắp xếp nó.) Nếu hai, hai bộ dữ liệu là hai thứ được thụt lề xa hơn, và chúng được nối với quy tắc mà bạn thấy. Ý nghĩa của hầu hết các quy tắc có thể được đoán một cách hợp lý (đặc biệt nếu bạn đã đọc một loạt các kế hoạch giải thích trước đây), tuy nhiên bạn có thể thử xác minh từng mục bằng cách xem tài liệu hoặc (dễ dàng hơn) bằng cách chỉ cần ném cụm từ vào Google cùng với một vài từ khóa như EXPLAIN.

Điều này rõ ràng không phải là một lời giải thích đầy đủ, nhưng nó cung cấp đủ ngữ cảnh mà bạn thường có thể tìm ra bất cứ điều gì bạn muốn. Ví dụ: xem xét kế hoạch này từ một cơ sở dữ liệu thực tế:

explain analyze 
select a.attributeid, a.attributevalue, b.productid 
from orderitemattribute a, orderitem b 
where a.orderid = b.orderid 
and a.attributeid = 'display-album' 
and b.productid = 'ModernBook'; 

------------------------------------------------------------------------------------------------------------------------------------------------------------ 

Merge Join (cost=125379.14..125775.12 rows=3311 width=29) (actual time=841.478..841.478 rows=0 loops=1) 
    Merge Cond: (a.orderid = b.orderid) 
    -> Sort (cost=109737.32..109881.89 rows=57828 width=23) (actual time=736.163..774.475 rows=16815 loops=1) 
     Sort Key: a.orderid 
     Sort Method: quicksort Memory: 1695kB 
     -> Bitmap Heap Scan on orderitemattribute a (cost=1286.88..105163.27 rows=57828 width=23) (actual time=41.536..612.731 rows=16815 loops=1) 
       Recheck Cond: ((attributeid)::text = 'display-album'::text) 
       -> Bitmap Index Scan on (cost=0.00..1272.43 rows=57828 width=0) (actual time=25.033..25.033 rows=16815 loops=1) 
        Index Cond: ((attributeid)::text = 'display-album'::text) 
    -> Sort (cost=15641.81..15678.73 rows=14769 width=14) (actual time=14.471..16.898 rows=1109 loops=1) 
     Sort Key: b.orderid 
     Sort Method: quicksort Memory: 76kB 
     -> Bitmap Heap Scan on orderitem b (cost=310.96..14619.03 rows=14769 width=14) (actual time=1.865..8.480 rows=1114 loops=1) 
       Recheck Cond: ((productid)::text = 'ModernBook'::text) 
       -> Bitmap Index Scan on id_orderitem_productid (cost=0.00..307.27 rows=14769 width=0) (actual time=1.431..1.431 rows=1114 loops=1) 
        Index Cond: ((productid)::text = 'ModernBook'::text) 
Total runtime: 842.134 ms 
(17 rows) 

Hãy thử đọc nó cho chính mình và xem nó có hợp lý không.

Những gì tôi đọc là cơ sở dữ liệu đầu tiên quét chỉ mục id_orderitem_productid, sử dụng để tìm các hàng muốn từ orderitem, sau đó sắp xếp tập dữ liệu đó bằng cách sử dụng quicksort (sắp xếp sẽ thay đổi nếu dữ liệu không phù hợp với RAM) , rồi gạt sang một bên.

Tiếp theo, nó quét orditematt_attributeid_idx để tìm các hàng mà nó muốn từ orderitemattribute và sau đó sắp xếp tập dữ liệu đó bằng cách sử dụng quicksort.

Sau đó, lấy hai bộ dữ liệu và hợp nhất chúng. (Một phép nối hợp nhất là một loại hoạt động "nén" ở đó nó đi cùng hai tập hợp dữ liệu được sắp xếp song song, phát ra hàng được nối khi chúng khớp nhau.)

Như tôi đã nói, bạn làm việc thông qua phần bên trong của kế hoạch với phần bên ngoài, dưới lên trên.

13

PgAdmin sẽ hiển thị cho bạn bản trình bày đồ họa của gói giải thích. Chuyển đổi qua lại giữa hai người thực sự có thể giúp bạn hiểu ý nghĩa của văn bản. Tuy nhiên, nếu bạn chỉ muốn biết nó sẽ làm gì, bạn có thể chỉ sử dụng GUI.

15

Có một công cụ trợ giúp trực tuyến có sẵn, Depesz, sẽ làm nổi bật nơi các phần đắt tiền của kết quả phân tích.

cũng có một, đây là same results, để tôi làm rõ hơn vấn đề ở đâu.

+18

giải thích-analyze.info dường như không hoạt động, nhưng tôi đồng ý rằng http://explain.depesz.com/ rất hữu ích. – benvolioT

+1

http://explain.depesz.com rất hữu ích, đặc biệt là tab "Thống kê". –

0

Nếu bạn cài đặt pgadmin, có một nút Giải thích cũng như cho đầu ra văn bản vẽ sơ đồ về những gì đang diễn ra, hiển thị các bộ lọc, sắp xếp và hợp nhất các tập hợp con mà tôi thấy thực sự hữu ích để xem điều gì đang xảy ra.

24

Phần tôi luôn thấy khó hiểu là chi phí khởi động so với tổng chi phí. Tôi Google này mỗi khi tôi quên nó, điều đó đưa tôi trở lại đây, điều này không giải thích được sự khác biệt, đó là lý do tại sao tôi viết câu trả lời này. Đây là những gì tôi đã lượm lặt từ số Postgres EXPLAIN documentation, giải thích khi tôi hiểu nó.

Dưới đây là một ví dụ từ một ứng dụng quản lý một diễn đàn:

EXPLAIN SELECT * FROM post LIMIT 50; 

Limit (cost=0.00..3.39 rows=50 width=422) 
    -> Seq Scan on post (cost=0.00..15629.12 rows=230412 width=422) 

Dưới đây là lời giải thích đồ họa từ pgAdmin:

graphical explanation of first query

(Khi bạn đang sử dụng pgAdmin, bạn có thể trỏ chuột vào một thành phần để đọc chi tiết chi tiết.)

Chi phí được biểu thị dưới dạng một bộ dữ liệu, ví dụ: chi phí của LIMITcost=0.00..3.39 và chi phí quét tuần tự postcost=0.00..15629.12. Số đầu tiên trong tuple là chi phí khởi động và số thứ hai là tổng chi phí . Bởi vì tôi đã sử dụng EXPLAIN và không phải EXPLAIN ANALYZE, các chi phí này là ước tính, không phải là các biện pháp thực tế.

  • Chi phí khởi động là một khái niệm phức tạp. Nó không chỉ đại diện cho khoảng thời gian trước thành phần đó bắt đầu. Nó đại diện cho khoảng thời gian giữa khi thành phần bắt đầu thực thi (đọc dữ liệu) và khi thành phần xuất ra hàng đầu tiên của nó.
  • Tổng chi phí là toàn bộ thời gian thực hiện của thành phần, từ khi nó bắt đầu đọc dữ liệu đến khi nó kết thúc ghi đầu ra của nó.

Là một biến chứng, mỗi chi phí của nút "cha mẹ" đều bao gồm chi phí của các nút con của nó. Trong phần trình bày văn bản, cây được biểu diễn bằng thụt đầu dòng, ví dụ: LIMIT là một nút cha và Seq Scan là con của nó. Trong biểu diễn PgAdmin, các mũi tên trỏ từ con sang mẹ - hướng của luồng dữ liệu - điều này có thể phản trực giác nếu bạn quen với lý thuyết đồ thị.

Tài liệu nói rằng chi phí bao gồm tất cả các nút con, nhưng lưu ý rằng tổng chi phí của phụ huynh 3.39 nhỏ hơn nhiều so với tổng chi phí của nó là 15629.12. Tổng chi phí không được bao gồm bởi vì một thành phần như LIMIT không cần xử lý toàn bộ đầu vào của nó. Xem ví dụ EXPLAIN SELECT * FROM tenk1 WHERE unique1 < 100 AND unique2 > 9000 LIMIT 2; trong Postgres EXPLAIN documentation. Trong ví dụ trên, thời gian khởi động là 0 cho cả hai thành phần, vì không thành phần nào cần thực hiện bất kỳ quá trình xử lý nào trước khi bắt đầu viết hàng: quét tuần tự đọc hàng đầu tiên của bảng và phát ra nó. Các LIMIT đọc hàng đầu tiên của nó và sau đó phát ra nó.

Khi nào một thành phần cần thực hiện nhiều quá trình xử lý trước khi có thể bắt đầu xuất bất kỳ hàng nào?Có rất nhiều lý do có thể, nhưng hãy xem một ví dụ rõ ràng. Dưới đây là cùng một truy vấn từ trước nhưng bây giờ chứa một ORDER BY khoản:

EXPLAIN SELECT * FROM post ORDER BY body LIMIT 50; 

Limit (cost=23283.24..23283.37 rows=50 width=422) 
    -> Sort (cost=23283.24..23859.27 rows=230412 width=422) 
     Sort Key: body 
     -> Seq Scan on post (cost=0.00..15629.12 rows=230412 width=422) 

Và đồ họa:

graphical explanation of second query

Một lần nữa, quá trình quét tuần tự trên post không có chi phí khởi động: nó bắt đầu xuất ra hàng ngay lập tức . Nhưng loại này có chi phí khởi động đáng kể 23283.24 vì nó phải sắp xếp toàn bộ bảng trước khi nó có thể xuất ra ngay cả một hàng đơn. Tổng chi phí của loại 23859.27 chỉ cao hơn một chút so với chi phí khởi động, phản ánh thực tế là khi toàn bộ tập dữ liệu đã được sắp xếp, dữ liệu được sắp xếp có thể được phát ra rất nhanh.

Lưu ý rằng thời gian khởi động của LIMIT23283.24 chính xác bằng thời gian khởi động sắp xếp. Điều này không phải vì bản thân có một thời gian khởi động cao. Nó thực sự không có thời gian khởi động của chính nó, nhưng EXPLAIN cuộn lên tất cả các chi phí con cho mỗi phụ huynh, do đó, thời gian khởi động LIMIT bao gồm tổng thời gian khởi động của các con của nó.

Việc cuộn chi phí này có thể gây khó khăn cho việc hiểu chi phí thực hiện của từng thành phần riêng lẻ. Ví dụ: LIMIT của chúng tôi không có thời gian khởi động, nhưng điều đó không rõ ràng ngay từ cái nhìn đầu tiên. Vì lý do này, một số người khác liên kết với explain.depesz.com, một công cụ được tạo bởi Hubert Lubaczewski (a.k.a. depesz) giúp hiểu được EXPLAIN bởi - trong số những thứ khác - trừ đi chi phí con từ chi phí gốc. Ông đề cập đến một số phức tạp khác trong a short blog post về công cụ của mình.

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