Сорок секунд: первый EXPLAIN ANALYZE

Оценка против факта

12 мин
Чему научишься
  • находить в плане главную пару чисел: rows в оценке и rows в факте
  • понимать, откуда у прогнозы: статистика, которую собирает команда ANALYZE
  • читать сигнал «карты устарели»: расхождение оценки и факта на порядок
  • старить статистику своими руками — и смотреть, как штурман слепнет

После вахты с буферами ты спускаешься в машинное отделение уже как к себе домой: люк, трап, ровный гул. КВЕРИ ждёт не у — у стойки в глубине зала, которую ты до сих пор принимал за архивный шкаф. Внутри — карты. Не палуб и не коридоров: карты данных. На верхнем листе — журнал жизнеобеспечения: сколько в нём строк, какие статусы встречаются на каждом шагу, какие — почти никогда. Штурман не заглядывает в сами данные, когда прокладывает маршрут: на это ушло бы больше времени, чем на сам рейс. Он смотрит сюда — в карты.

Ты вспоминаешь вчерашний план: в каждом узле стояло два rows — одно в первой паре скобок, другое во второй. Вчера они дружили: штурман обещал — и почти угадал.

КВЕРИ: Первое — то, что штурман ожидал по картам. Второе — то, что случилось в рейсе. Пока эти числа рядом, машина видит архив таким, какой он есть. Вопрос дня: что будет, когда они разойдутся?

Высокая приборная панель, где у каждого манометра по две стрелки под одним стеклом: белая — прогноз, оранжевая — факт; слева пары почти совпадают, справа одна пара разошлась до края шкалы и стекло треснуло; на полке панели сидит робот-кот и смотрит прямо на этот прибор, на его ободе — попугай.
У каждого узла две пары показаний. Пока прогноз и факт рядом — плану можно верить; разрыв и есть место поломки.

Оценка и факт

Каждый узел плана под EXPLAIN ANALYZE несёт две пары скобок, и в каждой есть своё rows:

Seq Scan on ls_readings  (cost=0.00..3763.00 rows=<оценка> ...) (actual time=... rows=<факт> loops=1)
  • rows в оценке — сколько строк узел вернёт по прогнозу . Это число существует ещё ДО исполнения: из него складываются попугаи cost — тот самый ценник, по которому штурман сравнивает маршруты и берёт самый дешёвый. Ты видел его под чистым EXPLAIN.
  • rows в факте — сколько строк узел вернул на самом деле. Это число появляется только после рейса, его дописывает хронометраж.

С каждым по отдельности ты уже знаком. Сегодняшний навык — их сверка: это главная пара чисел плана, и читать её ты будешь до конца курса.

Откуда берётся прогноз? Планировщик держит статистику — компактную карту каждой таблицы: сколько в ней строк, какие значения частые, какие редкие. Карту рисует команда ANALYZE <таблица>: она проходит по случайной выборке строк и перерисовывает её. Не путай с EXPLAIN ANALYZE — имена совпали, но инструменты разные: команда ANALYZE рисует карты, EXPLAIN ANALYZE исполняет запрос и показывает, что вышло.

Отсюда правило чтения — держи его под рукой весь курс:

Расхождение оценки и факта в разы — шум. Расхождение на ПОРЯДОК — сигнал. Прогноз из случайной выборки не обязан попадать строка в строку, а ошибиться вдвое для него — будни. Но если штурман ждал тысячу строк, а приехало двадцать тысяч, — маршрут выбран по неверной карте.

Проверим карты станции. Песочница пересеивает журнал перед каждым запуском, и посев заканчивается командой ANALYZE — статистика свежайшая. Спросим журнал об авариях:

Две пары скобок у каждого узла: прогноз штурмана и факт секундомера — поломка живёт в разрыве
Смотри на пару rows. Оценка — около девятисот, у каждого прогона своя, сотня-другая в ту или другую сторону: карты рисуются по случайной выборке, поэтому прогноз слегка дышит. Факт — ровно rows=900. Расхождение копеечное: карты свежие, штурман видит журнал таким, какой он есть.

Карты стареют

Статистика — , а не зеркало. Команда ANALYZE отсняла таблицу — и с этой секунды карта начинает отставать от территории: данные меняются, снимок — нет, до следующего ANALYZE. На карты пересобирает фоновый процесс, но приходит он по своему расписанию, когда изменений накопится достаточно, — а данные не ждут. Между «архив изменился» и «карты перерисованы» всегда есть окно. В этом окне слеп.

Устроим такое окно своими руками. Знакомься: датчик 13, самый шумный на станции, — на него и так приходится каждая пятая строка журнала. Сегодня он сорвался: каскадный сбой, и за одно утро в журнал упало двадцать тысяч fault-показаний. Ячейка ниже сама дописывает их в конец журнала и — не давая машине перерисовать карты — задаёт планировщику тот же вопрос об авариях:

Оценка осталась прежнего порядка — около тысячи: штурман смотрит в карту, снятую ДО каскада. (Она может выйти чуть выше, чем в прошлой ячейке: что журнал потолстел, штурман видит и без карты, — но долю аварий в нём он не пересчитывал.) Факт — rows=20900, в двадцать раз больше прогноза. Расхождение на порядок: планировщик ослеп. А Rows Removed by Filter: 179100 не изменилось: в отсев ушли те же старые строки — все двадцать тысяч новых показаний аварийные, и фильтр их пропускает.

Чем опасна старая карта

Сегодня запрос выжил: узел один, и полный проход остаётся полным проходом, сколько бы строк ни прошло фильтр. Опасность начинается в планах побольше. По прогнозу «аварий почти нет» штурман смело выбирает маршруты, рассчитанные на сотни строк, — а поедут по ним двадцать тысяч. Неверная оценка в нижнем узле отравляет все этажи над ним: соединения, сортировки, порядок таблиц — каждое следующее решение построено на числе, которого не существует.

Диагноз ясен, и лечение очевидно: перерисовать карту. Допиши в ячейке выше ANALYZE ls_readings; между вставкой и запросом и перезапусти — оценка подойдёт к факту почти вплотную. А вот из чего карты сделаны внутри — какие значения штурман помнит поимённо и как гадает об остальных — разберём в штурманской рубке, в седьмой главе.

КВЕРИ: Заметь: машина не сломалась. Она честно исполнила лучший маршрут по той карте, что лежала на столе. Хочешь другой маршрут — принеси свежую карту.

Приборы собраны: чертёж, хронометраж, ввод-вывод и сверка прогноза с фактом. В следующем уроке сложим их в единый порядок действий — воркфлоу, с которым инженер подходит к любому медленному запросу.

Проверь себя
Три узла из трёх разных планов. По паре rows (оценка → факт) найди узел, где планировщик ослеп:
Закрепление: реши задачи
Решено 0 из 1