1

Запросы выполняются на большом столе с 11 миллионами строк. Я уже выполнил ANALYZE в таблице перед выполнением запроса.Насколько надежным является измерение затрат в PostgreSQL Explain Plan?

Запрос 1:

SELECT * 
FROM accounts t1 
LEFT OUTER JOIN accounts t2 
    ON (t1.account_no = t2.account_no 
     AND t1.effective_date < t2.effective_date) 
WHERE t2.account_no IS NULL; 

Поясните Анализ:

Hash Anti Join (cost=480795.57..1201111.40 rows=7369854 width=292) (actual time=29619.499..115662.111 rows=1977871 loops=1) 
    Hash Cond: ((t1.account_no)::text = (t2.account_no)::text) 
    Join Filter: ((t1.effective_date)::text < (t2.effective_date)::text) 
    -> Seq Scan on accounts t1 (cost=0.00..342610.81 rows=11054781 width=146) (actual time=0.025..25693.921 rows=11034070 loops=1) 
    -> Hash (cost=342610.81..342610.81 rows=11054781 width=146) (actual time=29612.925..29612.925 rows=11034070 loops=1) 
     Buckets: 2097152 Batches: 1 Memory Usage: 1834187kB 
     -> Seq Scan on accounts t2 (cost=0.00..342610.81 rows=11054781 width=146) (actual time=0.006..22929.635 rows=11034070 loops=1) 
Total runtime: 115870.788 ms 

Сметная стоимость ~ 1200000 и фактическое потраченное время ~ 1,9 минут.

Запрос 2:

SELECT t1.* 
FROM accounts t1 
LEFT OUTER JOIN accounts t2 
    ON (t1.account_no = t2.account_no 
     AND t1.effective_date < t2.effective_date) 
WHERE t2.account_no IS NULL; 

Поясните Анализ:

Hash Anti Join (cost=480795.57..1201111.40 rows=7369854 width=146) (actual time=13365.808..65519.402 rows=1977871 loops=1) 
    Hash Cond: ((t1.account_no)::text = (t2.account_no)::text) 
    Join Filter: ((t1.effective_date)::text < (t2.effective_date)::text) 
    -> Seq Scan on accounts t1 (cost=0.00..342610.81 rows=11054781 width=146) (actual time=0.007..5032.778 rows=11034070 loops=1) 
    -> Hash (cost=342610.81..342610.81 rows=11054781 width=18) (actual time=13354.219..13354.219 rows=11034070 loops=1) 
     Buckets: 2097152 Batches: 1 Memory Usage: 545369kB 
     -> Seq Scan on accounts t2 (cost=0.00..342610.81 rows=11054781 width=18) (actual time=0.011..8964.571 rows=11034070 loops=1) 
Total runtime: 65705.707 ms 

По оценкам, стоимость ~ 1,2 млн (снова) но фактическое время, затраченное является < 1,1 минуты.

Запрос 3:

SELECT * 
FROM accounts 
WHERE (account_no, 
     effective_date) IN 
    (SELECT account_no, 
      max(effective_date) 
    FROM accounts 
    GROUP BY account_no); 

Поясните Анализ:

Nested Loop (cost=406416.19..502216.84 rows=2763695 width=146) (actual time=31779.457..917543.228 rows=1977871 loops=1) 
    -> HashAggregate (cost=406416.19..406757.45 rows=34126 width=43) (actual time=31774.877..33378.968 rows=1977425 loops=1) 
     -> Subquery Scan on "ANY_subquery" (cost=397884.72..404709.90 rows=341259 width=43) (actual time=27979.226..29841.217 rows=1977425 loops=1) 
       -> HashAggregate (cost=397884.72..401297.31 rows=341259 width=18) (actual time=27979.224..29315.346 rows=1977425 loops=1) 
        -> Seq Scan on accounts (cost=0.00..342610.81 rows=11054781 width=18) (actual time=0.851..16092.755 rows=11034070 loops=1) 
    -> Index Scan using accounts_idx2 on accounts (cost=0.00..2.78 rows=1 width=146) (actual time=0.443..0.445 rows=1 loops=1977425) 
     Index Cond: (((account_no)::text = ("ANY_subquery".account_no)::text) AND ((effective_date)::text = "ANY_subquery".max)) 
Total runtime: 918039.614 ms 

Сметная стоимость ~ 502000 но фактическое потраченное время ~ 15,3 минут!

  • Насколько надежным является вывод EXPLAIN?
  • ли мы всегда должны EXPLAIN ANALYZE, чтобы увидеть, как наш запрос будет выполнять на реальных данных, а не размещает доверие о том, сколько планировщик запросов думает это будет стоить?
+0

Стоимость - это произвольное число. Затраты только относительно друг друга, у них нет единиц и никакого внешнего смысла. Вы можете оценить приблизительный коэффициент пересчета от стоимости запроса до времени выполнения для вашей машины, сравнив калькуляцию с временем выполнения для кучи запросов, но это единственный способ. Надежность оценок затрат основана в основном на том, насколько хороша работа, которую делает планировщик, насколько актуальна и детализирована статистика вашего стола, и сталкиваетесь ли вы с известными проблемами оценки стоимости, такими как коррелированные столбцы. –

+0

_ «Вы можете оценить грубый коэффициент пересчета от стоимости запроса до времени выполнения для вашей машины, сравнив калькуляцию с временем выполнения для кучки запросов». Этот грубый коэффициент пересчета абсолютно бесполезен в приведенном выше случае. Если я грубо оцениваю коэффициент пересчета времени на количество запросов 1 и 2, я думаю, что запрос 3 не должен занимать более 45 секунд. ** Но это занимает более 15 минут? Почему? ** – ADTC

+0

Иными словами, стоимость кажется очень ошибочной. Если бы я доверял стоимости, я бы выбрал запрос 3 по запросу 2, но фактическое время выполнения показывает, что я должен действительно выбирать запрос 2 по запросу 3. – ADTC

ответ

2

Они надежны, за исключением случаев, когда они не являются. Вы не можете обобщить.

Похоже, что он значительно недооценивает количество разных account_no, которое он найдет (думает, что найдет 34126 на самом деле найдено 1977425). Ваш default_statistics_target может быть недостаточно высоким, чтобы получить хорошую оценку для этого столбца.

+0

Это хороший совет! Я думаю, что один из признаков того, когда оценка плоха, - это когда количество оцениваемых строк недостаточно близко к фактическому количеству строк. – ADTC

Смежные вопросы