Я ускорил запрос в 75 раз. Через две недели оказалось, что дело было не в запросе
cmtn 17 минут назад Объяснить с Я ускорил запрос в 75 раз. Через две недели оказалось, что дело было не в запросе 5 мин 351 PostgreSQL * Базы данных * SQL * 18 сентября я добавлял в карту парковок второй город. Миграция...
<5 — 2026'da uzaya kaç SpaceX Starship fırlatması ulaşacak?
Значимый прорыв формирует отрасль ИИ: cmtn 17 минут назад Объяснить с Я ускорил запрос в 75 раз. Через две недели оказалось, что дело было не в запросе 5 мин 351 PostgreSQL * Базы данных * SQL * 18 сентября я добавлял в карту парковок второй город. Миграция завела колонку city у таблицы парковок, дальше надо было научить API отдавать данные по одному городу.
Запрос, который показывает текущую занятость, устроен так: сначала подзапрос «самый свежий замер по каждой парковке», потом join обратно к замерам, чтобы достать строки целиком. Фильтр по городу я поставил в подзапрос. Это же очевидно: сужаем выборку как можно раньше, чтобы агрегат считался по меньшему объёму.
Технические детали
Даже комментарий написал, уверенный такой:# Сузить до города дешевле на подзапросе: иначе max(time) считается # по всем парковкам мира, а потом большая часть отбрасывается. join(ParkingSpot, ParkingSpot. id == ParkingOccupancy.
city == city ) На тестовой базе отработало мгновенно. На продеЗапрос завис. Не «стал медленным», а именно завис: браузер отваливался по таймауту раньше, чем приходил ответ.
Пошёл мерить на боевой базе. без join 0,71 с с join 53,7 с Семьдесят пять раз. Одна добавленная строчка join, которая по всем учебникам должна была ускорить.
Отраслевые последствия
parking_occupancy — гипертаблица TimescaleDB: на тот момент 4,6 млн строк, разложенных по 78 чанкам. Планировщик с добавленным join переставал видеть её как единое целое и уходил в nested loop с bitmap-сканом по каждой парковке в каждом чанке. Двести десять парковок на семьдесят восемь чанков.
Подзапрос вернул в исходный вид, а по городу стал отсекать уже готовый результат:# ВАЖНО: город здесь НЕ фильтруется. # Замерено на боевой базе: без join 0,71 с, с join 53,7 с subq = ( self. query( ParkingOccupancy.
max(ParkingOccupancy. group_by(ParkingOccupancy. subquery() ) А фильтр уехал в цикл по результату, где строк меньше тысячи и стоимость нулевая:for occ in latest_rows: spot = spots.
Этот прогресс даёт важные сигналы о будущем отрасли, и технологический мир внимательно наблюдает.






