ประสิทธิภาพของ postgres_fdw ช้า


12

แบบสอบถามต่อไปนี้ในต่างประเทศใช้เวลาประมาณ 5 วินาทีในการดำเนินการกับ 3.2 ล้านแถว:

SELECT x."IncidentTypeCode", COUNT(x."IncidentTypeCode") 
FROM "IntterraNearRealTimeUnitReflexes300sForeign" x 
WHERE x."IncidentDateTime" >= '05/01/2016' 
GROUP BY x."IncidentTypeCode" 
ORDER BY 1;

เมื่อฉันเรียกใช้คิวรีเดียวกันในตารางปกติมันจะส่งคืนภายใน 0.6 วินาที แผนการดำเนินการแตกต่างกันมาก:

ตารางปกติ

Sort  (cost=226861.20..226861.21 rows=4 width=4) (actual time=646.447..646.448 rows=7 loops=1) 
  Sort Key: "IncidentTypeCode" 
  Sort Method: quicksort  Memory: 25kB 
  -> HashAggregate (cost=226861.12..226861.16 rows=4 width=4) (actual  time=646.433..646.434 rows=7 loops=1)
     Group Key: "IncidentTypeCode"
     -> Bitmap Heap Scan on "IntterraNearRealTimeUnitReflexes300s" x  (cost=10597.63..223318.41 rows=708542 width=4) (actual time=74.593..342.110 rows=709376 loops=1) 
        Recheck Cond: ("IncidentDateTime" >= '2016-05-01 00:00:00'::timestamp without time zone) 
        Rows Removed by Index Recheck: 12259 
        Heap Blocks: exact=27052 lossy=26888
        -> Bitmap Index Scan on idx_incident_date_time_300  (cost=0.00..10420.49 rows=708542 width=0) (actual time=69.722..69.722 rows=709376 loops=1) 
           Index Cond: ("IncidentDateTime" >= '2016-05-01 00:00:00'::timestamp without time zone) 

Planning time: 0.165 ms 
Execution time: 646.512 ms

ตารางต่างประเทศ

Sort  (cost=241132.04..241132.05 rows=4 width=4) (actual time=4782.110..4782.112 rows=7 loops=1)   
  Sort Key: "IncidentTypeCode" 
  Sort Method: quicksort  Memory: 25kB
  -> HashAggregate  (cost=241131.96..241132.00 rows=4 width=4) (actual time=4782.097..4782.100 rows=7 loops=1)
     Group Key: "IncidentTypeCode"
     -> Foreign Scan on "IntterraNearRealTimeUnitReflexes300sForeign" x  (cost=10697.63..237589.25 rows=708542 width=4) (actual time=1.916..4476.946 rows=709376 loops=1) 

Planning time: 1.413 ms 
Execution time: 4782.660 ms

ฉันคิดว่าฉันจ่ายราคาสูงสำหรับGROUP BYประโยคที่ไม่ได้ถูกส่งไปยังเซิร์ฟเวอร์ต่างประเทศเมื่อฉันEXPLAIN VERBOSE:

SELECT
    "IncidentTypeCode"
FROM
    PUBLIC ."IntterraNearRealTimeUnitReflexes300s"
WHERE
    (
        (
            "IncidentDateTime" >= '2016-05-01 00:00:00' :: TIMESTAMP WITHOUT TIME ZONE
        )
    )

ส่งคืนแถว 700k มีวิธีแก้ไขไหม?

ฉันใช้เวลามากอ่านหน้าเอกสารนี้เมื่อวานนี้และคิดว่าฉันได้พบคำตอบโดยตั้งค่าuse_remote_estimateเป็นจริง แต่ก็ไม่มีผล

ฉันมีสิทธิ์เข้าถึงเซิร์ฟเวอร์ต่างประเทศเพื่อสร้างวัตถุหากจำเป็น ค่าการประทับเวลาในส่วนWHEREคำสั่งสามารถเป็นอะไรก็ได้ มันไม่ได้มาจากรายการของค่าที่กำหนดไว้ล่วงหน้า


3
มีการปรับปรุงแบบเลื่อนลงใน 9.6 ที่อาจเป็นที่สนใจ: wiki.postgresql.org/wiki/NewIn96#postgres_fdw
แจ็คบอกว่าลอง topanswers.xyz

เมื่อคุณพูดว่าโต๊ะปกติเทียบกับต่างประเทศคุณกำลังวิ่งข้ามโต๊ะเดียวกัน (ในพื้นที่และจากระยะไกล) หรือตารางที่แตกต่างกันจริง ๆ (มันอ่านราวกับว่าพวกเขาเป็น) ถ้าพวกเขาต่างกันตรวจสอบการจัดทำดัชนีบนเซิร์ฟเวอร์ระยะไกล ในขณะที่คุณกำลังอ่านแหล่งข้อมูลที่แตกต่างอย่างสิ้นเชิงIntterraNearRealTimeUnitReflexes300sForeignเทียบกับIntterraNearRealTimeUnitReflexes300sและidx_incident_date_time_300 ฉันคิดว่า 300s นั้นเหมือนกัน แต่มันอาจคุ้มค่าที่จะตรวจสอบว่าidx_incident_date_time_300ดัชนีนั้นมีอยู่บนเซิร์ฟเวอร์ต่างประเทศหรือไม่
Ste Bov

2
จากสิ่งที่ฉันเข้าใจการรวม (COUNT) จะไม่ถูกส่งไปยังเซิร์ฟเวอร์ระยะไกลซึ่งจะอธิบายเวลาที่ขอนาน ดูเหมือนว่าคุณลักษณะนี้จะปรากฏในหน้า 10 - depesz.com/2016/10/25/ …
เจอโรมวากเนอร์

@JeromeWAGNER - ยอดเยี่ยม
J-DawG

คำตอบ:


7

หากคุณใช้use_remote_estimateตรวจสอบให้แน่ใจว่าได้วิเคราะห์ตารางต่างประเทศ (ฉันเห็นการประมาณค่าที่ใกล้เคียงกับที่ส่งคืนคุณอาจทำเช่นนั้น) นอกจากนี้ยังไม่มีการปรับปรุงแบบขยายลงในรุ่น <9.5 ฉันยังสมมติว่าคุณมีโครงสร้างตารางเดียวกันบนเซิร์ฟเวอร์ระยะไกลอย่างใดอย่างหนึ่ง (รวมถึงดัชนี) หากจำเป็นต้องใช้บิตแมปเนื่องจากความสำคัญน้อยก็จะไม่ใช้ดัชนีเนื่องจากข้อ จำกัด ของกลไกการเลื่อนลง คุณอาจต้องการลดจำนวนแถวที่ส่งคืนเพื่อบังคับให้สแกนดัชนี BTREE ( ช่วงการประทับเวลา) น่าเสียดายที่ไม่มีวิธีใหม่ ๆ ในการหลีกเลี่ยง SeqScan บนเซิร์ฟเวอร์ระยะไกลหากตัวกรองส่งกลับค่า + 10% ของแถวของตาราง (อาจเปลี่ยนแปลงเปอร์เซ็นต์นี้หากผู้วางแผนพิจารณาว่าการสแกนทั้งตารางนั้นถูกกว่าการอ่าน) หากคุณใช้ SSD คุณอาจพบว่ามีประโยชน์ในการปรับแต่งrandom_page_cost)

คุณสามารถใช้ CTE เพื่อแยกกลุ่มตามพฤติกรรม:

WITH atable AS (
    SELECT "IncidentTypeCode"
    FROM PUBLIC ."IntterraNearRealTimeUnitReflexes300s"
    WHERE 
       ("IncidentDateTime" 
              BETWEEN '2016-05-01 00:00:00'::TIMESTAMP WITHOUT TIME ZONE 
                  AND '2016-05-02 00:00:00'::TIMESTAMP WITHOUT TIME ZONE)
)
SELECT atable."IncidentTypeCode", COUNT(atable.IncidentTypeCode) 
FROM atable
GROUP BY atable."IncidentTypeCode" 
ORDER BY atable."IncidentTypeCode";

1
ประสิทธิภาพการทำงานเหมือนกันโดยใช้ CTE จะลองใช้การตั้งค่า random_page_cost ขอบคุณ!
J-DawG
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.