Intereting Posts
Как заставить запрос не использовать индекс в данной таблице? Извлечение из большого xml запроса слишком длительное с строковым литералом Условное единственное ограничение с несколькими полями в oracle db Как вы запускаете один запрос через mysql из командной строки? Как печатать десятичный номер из сохраненной строковой даты (PL / SQL) Как сделать разделение в SQL Это нормально, если у вас есть алфавитно-цифровое поле в качестве PrimaryKey? MySQL проверяет, перекрывается ли два диапазона дат со входом В чем разница между предложением where и предложением, когда таблица оставила соединение? Расчет расстояния между двумя точками с помощью sql Что значит @ ! в выражении От mysql для получения формата 25/04 месяцев, где формат даты – 1988-04-04? Sybase sp_who усекает имя хоста MySQL: доступ запрещен для пользователей к базе данных пожалуйста, поправьте меня с запросом sql

Насколько надежным является измерение затрат в PostgreSQL Explain Plan?

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

Запрос 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 

Ориентировочная стоимость составляет ~ 1,2 миллиона, а фактическое время составляет ~ 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 

Ориентировочная стоимость составляет ~ 502 000, но фактическое время составляет ~ 15,3 минуты!

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

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

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