เลื่อนระดับแผนแบบสอบถามของการเรียกใช้ฟังก์ชันที่เขียนใน plpgsql


19

มันเป็นไปได้เมื่อใช้pgadminหรือplsqlจะได้รับถือของแผนแบบสอบถามสำหรับคำสั่ง SQL ดำเนินการภายในU ser d efined ตื่นเต้น (UDF) EXPLAINโดยใช้ ดังนั้นฉันจะได้รับแผนแบบสอบถามสำหรับการร้องขอ UDF โดยเฉพาะได้อย่างไร ฉันเห็น UDF ที่แยกออกไปเป็นการดำเนินการเดียวF()ใน pgadmin

ฉันดูเอกสารแล้ว แต่หาอะไรไม่เจอ

ขณะนี้ฉันกำลังดึงคำแถลงและเรียกใช้ด้วยตนเอง แต่สิ่งนี้จะไม่ถูกตัดออกไปสำหรับข้อความค้นหาขนาดใหญ่

ตัวอย่างเช่นพิจารณา UDF ด้านล่าง UDF นี้แม้ว่ามันจะมีความสามารถในการพิมพ์สตริงการสืบค้นของมันจะไม่ทำงานกับการคัดลอกวางเพราะมันมีตารางชั่วคราวที่สร้างขึ้นในท้องถิ่นซึ่งไม่มีอยู่เมื่อคุณวางและดำเนินการ

CREATE OR REPLACE FUNCTION get_paginated_search_results(
    forum_id_ INTEGER,
    query_    CHARACTER VARYING,
    from_date_ TIMESTAMP WITHOUT TIME ZONE DEFAULT NULL,
    to_date_ TIMESTAMP WITHOUT TIME ZONE DEFAULT NULL,
    in_categories_ INTEGER[] DEFAULT '{}')
RETURNS SETOF post_result_entry AS $$
DECLARE
    join_string CHARACTER VARYING := ' ';
    from_where_date CHARACTER VARYING := ' ';
    to_where_date CHARACTER VARYING := ' ';
    query_string_ CHARACTER VARYING := ' ';
BEGIN
    IF NOT from_date_ IS NULL THEN
        from_where_date := ' AND fp.posted_at > ''' || from_date_ || '''';
    END IF;

    IF NOT to_date_ IS NULL THEN
        to_where_date := ' AND fp.posted_at < ''' || to_date_ || '''';
    END IF;

    CREATE LOCAL TEMP TABLE un_cat(id) ON COMMIT DROP AS (select * from unnest(in_categories_)) ;

    if in_categories_ != '{}' THEN
        join_string := ' INNER JOIN forum_topics ft ON fp.topic_id = ft.id ' ||
        ' INNER JOIN un_cat uc ON uc.id = ft.category_id ' ;
    END IF;

    query_string_ := '
    SELECT index,posted_at,post_text,name,join_date,quotes
    FROM forum_posts fp
    INNER JOIN forum_user fu ON
    fu.forum_id = fp.forum_id AND fu.id = fp.user_id' ||
        join_string
    ||
    'WHERE fu.forum_id = ' || forum_id_ || ' AND
    to_tsvector(''english'',fp.post_text) @@ to_tsquery(''english'','''|| query_||''')' || 
        from_where_date || 
        to_where_date
    ||';';

    RAISE NOTICE '%', query_string_ ;

    RETURN QUERY
    EXECUTE query_string_;
END;
$$ LANGUAGE plpgsql;

คำตอบ:


16

คุณควรใช้คำอธิบายอัตโนมัติ เปิดใช้งานและ

SET auto_explain.log_min_duration = 0;

และคุณควรได้รับแผนในบันทึกของคุณสำหรับคำสั่งทั้งหมดที่ทำงานในเซสชันนั้น

คุณอาจต้องการตั้งค่า

SET auto_explain.log_analyze = true; แต่คุณจะต้องวิ่งทุกอย่างเป็นสองเท่า - หนึ่งครั้งสำหรับ 'ของจริง' และหนึ่งครั้งเพื่ออธิบายการวิเคราะห์ ในระหว่างขั้นตอนการทดสอบประสิทธิภาพแบบไม่กำหนดเวลาผลลัพธ์นี้อาจมีประโยชน์มากกว่าแผนการอธิบายเพียงอย่างเดียวเนื่องจากเป็นสิ่งที่เกิดขึ้นจริงตามแผน


4
เป็น @Erwin ชี้ให้เห็นด้านล่างคุณควรตั้งค่า auto_explain.log_nested_statements = ON เช่นกัน
rfusca

ขอบคุณที่ทำเคล็ดลับ น่าเสียดายที่ฟังก์ชั่นนี้ไม่สามารถเข้าถึงได้ผ่านทาง GUI
Hassan Syed

@rfusca คุณจะใช้เป็นหลักทุกคู่ที่เป็นหลักฐานในการที่? การทดลองบางอย่างที่ฉันไม่ได้แสดงให้เห็นถึงพฤติกรรมนี้
เซบาสเตียนเดรสเลอร์

ตระหนักถึงสิ่งนี้คือการอ้างอิงฐานข้อมูลอายุ 7 ปี ณ จุดนี้ เป็นไปได้ว่าจะไม่ทำงานอย่างนั้นอีกต่อไปถ้าคุณไม่เห็นผลลัพธ์เดียวกัน
rfusca

16

ผมนอกเหนือจากคำแนะนำของ @ rfusca: คำสั่ง SQL ภายในฟังก์ชั่น plpgsql มีการพิจารณางบที่ซ้อนกันauto_explain.log_nested_statementsและคุณจำเป็นต้องตั้งค่าพารามิเตอร์เพิ่มเติม

ไม่เหมือนกับส่วนขยายอื่น ๆ คุณไม่จำเป็นต้องเรียกใช้ส่วนขยายCREATE EXTENSIONนี้ LOADเพียงแค่โหลดแบบไดนามิกในเซสชั่นของคุณด้วย เซสชันของคุณอาจมีลักษณะเช่นนี้:

LOAD 'auto_explain';
SET auto_explain.log_min_duration = 1; -- exclude very fast trivial queries
SET auto_explain.log_nested_statements = ON; -- statements inside functions
-- SET auto_explain.log_analyze = ON; -- get actual times, too
SELECT * FROM get_paginated_search_results(...);

อาจสร้างเอาต์พุตบันทึกจำนวนมาก ปัจจุบันคู่มือ auto_explain Depesz เขียนบทความในบล็อกเกี่ยวกับมันเมื่อมีการนำมาใช้กับ PostgreSQL 8.4


+1 - นานมากฉันลืมเกี่ยวกับการตั้งค่าบรรทัด
log_nested_statements

3
คุณสมควรได้รับเครดิตในการแสดงเครื่องมือที่เหมาะสมอยู่แล้ว
Erwin Brandstetter

ฉันมีฐานข้อมูล Postgres ในการให้บริการการจัดการของ Amazon (RDS) ซึ่งผลตอบแทนLOAD 'auto_explain'; ERROR: access to library "auto_explain" is not allowedในกรณีนั้นคืออะไร? ฉันเคยประสบความสำเร็จในการแฮ็คฟังก์ชั่นด้วยreturn query explain select …แต่ก็ลำบากและช้า
poshest
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.