продуктивність 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;

Коли я виконую той самий запит у звичайній таблиці, він повертається за .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 я припускаю, що 300-ті є однаковими, але, можливо, варто перевірити, чи idx_incident_date_time_300існує індекс на іноземному сервері
Ste Bov,

2
Як я розумію, агрегати (COUNT) не висуваються на віддалений сервер, що пояснює тривалий час запиту. Здається, ця функція з’явиться на сторінці 10 - depesz.com/2016/10/25/…
Jerome WAGNER

@JeromeWAGNER - Awesome
J-DawG

Відповіді:


7

Якщо ви використовуєте АНАЛІЗuse_remote_estimate запустити іноземну таблицю (я бачу оцінки досить близькі до повернених, ви, ймовірно, це зробили). Крім того, покращення розгортки недоступні у версії <9.5. Я також припускаю, що у вас є та ж структура таблиці на віддаленому сервері (включаючи індекси). Якщо растрова карта потрібна через низьку кардинальність, вона не використовуватиме індекс через обмеження механізму віджимання. Ви можете зменшити кількість повернених рядків, щоб змусити сканувати індекс BTREE ( діапазони часових позначок)). На жаль, не існує чистого способу уникнути SeqScan на віддаленому сервері, якщо фільтр поверне + 10% рядків таблиці (може змінюватись цей відсоток, якщо планувальник вважає, що сканування всієї таблиці дешевше, ніж шукати зчитування). Якщо ви використовуєте SSD, вам, ймовірно, стане в нагоді налаштування random_page_cost).

Ви можете використовувати CTE, щоб виділити поведінку GROUP BY:

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.