Запросы выполняются на большом столе с 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
, чтобы увидеть, как наш запрос будет выполнять на реальных данных, а не размещает доверие о том, сколько планировщик запросов думает это будет стоить?
Стоимость - это произвольное число. Затраты только относительно друг друга, у них нет единиц и никакого внешнего смысла. Вы можете оценить приблизительный коэффициент пересчета от стоимости запроса до времени выполнения для вашей машины, сравнив калькуляцию с временем выполнения для кучи запросов, но это единственный способ. Надежность оценок затрат основана в основном на том, насколько хороша работа, которую делает планировщик, насколько актуальна и детализирована статистика вашего стола, и сталкиваетесь ли вы с известными проблемами оценки стоимости, такими как коррелированные столбцы. –
_ «Вы можете оценить грубый коэффициент пересчета от стоимости запроса до времени выполнения для вашей машины, сравнив калькуляцию с временем выполнения для кучки запросов». Этот грубый коэффициент пересчета абсолютно бесполезен в приведенном выше случае. Если я грубо оцениваю коэффициент пересчета времени на количество запросов 1 и 2, я думаю, что запрос 3 не должен занимать более 45 секунд. ** Но это занимает более 15 минут? Почему? ** – ADTC
Иными словами, стоимость кажется очень ошибочной. Если бы я доверял стоимости, я бы выбрал запрос 3 по запросу 2, но фактическое время выполнения показывает, что я должен действительно выбирать запрос 2 по запросу 3. – ADTC