[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"question-sql-kak-analizirovat-proizvoditelnost-zaprosov-chto-takoe-explain-analyze":3},{"id":4,"slug":5,"topicId":6,"topicSlug":7,"topicName":8,"topicEmoji":9,"question":10,"answer":11,"codeLang":12,"codeSrc":12,"important":12,"commonMistakes":12,"modernUsage":12,"difficulty":13,"tags":14,"related":15,"progress":16,"seo":17},876,"kak-analizirovat-proizvoditelnost-zaprosov-chto-takoe-explain-analyze",25,"sql","SQL","🗃️","Как анализировать производительность запросов? Что такое EXPLAIN ANALYZE?","`EXPLAIN` — команда, которая показывает план выполнения запроса — последовательность операций, которые СУБД планирует выполнить для получения результата. `EXPLAIN ANALYZE` дополнительно выполняет запрос и показывает фактическое время и количество обработанных строк.\n\n### EXPLAIN vs EXPLAIN ANALYZE\n\n```sql\n-- Только план (запрос НЕ выполняется)\nEXPLAIN SELECT * FROM employees WHERE department = 'IT';\n\n-- План + фактическое выполнение\nEXPLAIN ANALYZE SELECT * FROM employees WHERE department = 'IT';\n\n-- Расширенный вывод с буферами\nEXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT)\nSELECT * FROM employees WHERE department = 'IT';\n```\n\n### Чтение плана выполнения\n\n\u003Cdetails>\u003Csummary>Пример вывода EXPLAIN ANALYZE\u003C\u002Fsummary>\n\n```\nSort  (cost=1234.56..1256.78 rows=8888 width=64) (actual time=12.345..15.678 rows=8500 loops=1)\n  Sort Key: salary DESC\n  Sort Method: quicksort  Memory: 1024kB\n  ->  Hash Join  (cost=100.00..900.00 rows=8888 width=64) (actual time=1.234..8.901 rows=8500 loops=1)\n        Hash Cond: (e.department_id = d.id)\n        ->  Seq Scan on employees e  (cost=0.00..500.00 rows=10000 width=48) (actual time=0.010..3.456 rows=10000 loops=1)\n        ->  Hash  (cost=80.00..80.00 rows=50 width=16) (actual time=0.123..0.124 rows=50 loops=1)\n              Buckets: 1024  Batches: 1  Memory Usage: 9kB\n              ->  Seq Scan on departments d  (cost=0.00..80.00 rows=50 width=16) (actual time=0.005..0.100 rows=50 loops=1)\nPlanning Time: 0.234 ms\nExecution Time: 16.789 ms\n```\n\n\u003C\u002Fdetails>\n\nКлючевые понятия:\n\n| Метрика | Описание |\n|---------|---------|\n| `cost` | Оценочная стоимость (начальная..общая) в условных единицах (НЕ миллисекунды) |\n| `rows` | Предполагаемое (estimated) и фактическое (actual) количество строк |\n| `actual time` | Реальное время выполнения (мс) для первой строки..всех строк |\n| `loops` | Сколько раз операция была выполнена (actual time надо умножить на loops) |\n| `width` | Средний размер строки в байтах |\n\n### Типы сканирования\n\n| Тип | Когда используется | Скорость |\n|-----|-------------------|---------|\n| Seq Scan | Нет подходящего индекса или таблица маленькая | Медленный на больших таблицах |\n| Index Scan | Есть индекс, высокая селективность | Быстрый |\n| Index Only Scan | Все нужные данные есть в индексе | Самый быстрый |\n| Bitmap Index Scan | Средняя селективность | Средний |\n\n### Типы соединений\n\n| Тип | Когда используется |\n|-----|-------------------|\n| Nested Loop | Малый внешний набор + индекс на внутреннем |\n| Hash Join | Средние\u002Fбольшие таблицы, нет индекса по ключу |\n| Merge Join | Данные уже отсортированы (по индексу) |\n\n\u003Cdetails>\u003Csummary>Практический пример оптимизации\u003C\u002Fsummary>\n\nИсходный медленный запрос:\n```sql\nEXPLAIN ANALYZE\nSELECT u.name, COUNT(o.id) AS order_count\nFROM users u\nLEFT JOIN orders o ON o.user_id = u.id\nWHERE o.created_at >= '2026-01-01'\nGROUP BY u.name\nORDER BY order_count DESC;\n```\n\nПлан показывает `Seq Scan on orders` с `actual time=500ms`.\n\nШаги оптимизации:\n\n1. Создать индекс:\n```sql\nCREATE INDEX idx_orders_user_date ON orders(user_id, created_at);\n```\n\n2. Проверить план заново — должен появиться `Index Scan` или `Bitmap Index Scan`.\n\n3. Если запрос фильтрует по диапазону дат, может помочь частичный индекс:\n```sql\nCREATE INDEX idx_orders_2026 ON orders(user_id)\nWHERE created_at >= '2026-01-01';\n```\n\n\u003C\u002Fdetails>\n\n### Важное\n\n- `EXPLAIN ANALYZE` реально выполняет запрос — для `DELETE`\u002F`UPDATE` используйте внутри транзакции с `ROLLBACK`\n- `BUFFERS` показывает количество обращений к кэшу и диску\n- Если `estimated rows` сильно отличается от `actual rows` — нужно выполнить `ANALYZE table_name`\n- Инструменты визуализации: [explain.dalibo.com](https:\u002F\u002Fexplain.dalibo.com), pgAdmin, DBeaver\n\n### Частые ошибки\n\n- Запускают `EXPLAIN ANALYZE DELETE FROM ...` без транзакции — данные удаляются\n- Путают `cost` с реальным временем — `cost` это условные единицы планировщика\n- Игнорируют `loops` — если операция выполняется 1000 раз, `actual time` нужно умножить на `loops`\n- Оптимизируют запрос на тестовой базе с малым количеством данных — планы будут другими на production\n\n> **На собеседовании:** объясните разницу между `EXPLAIN` (только план) и `EXPLAIN ANALYZE` (план + выполнение). Покажите, что умеете читать план: `Seq Scan` -> нужен индекс. Частая ошибка — путать `cost` с миллисекундами или забыть про `loops`.","","middle",[7],[],null,{"title":18,"description":19,"ogTitle":18,"ogDescription":20,"keywords":21,"schemaAnswer":22,"featuredSnippetReady":23},"Как анализировать производительность запросов? Что такое EXP — Gymterview","`EXPLAIN` — команда, которая показывает план выполнения запроса — последовательность операций, которые СУБД планирует выполнить для получения результата. `EXPLA","`EXPLAIN` — команда, которая показывает план выполнения запроса — последовательность операций, которые СУБД планирует вы",[7,13],"`EXPLAIN` — команда, которая показывает план выполнения запроса — последовательность операций, которые СУБД планирует выполнить для получения результата. `EXPLAIN ANALYZE` дополнительно выполняет запрос и показывает фактическое время и количество обработанных строк.",true]