Оптимизация SQL-запросов: Чтение планов выполнения и исправление медленных запросов с указанием времени
Перестаньте гадать, почему запрос выполняется медленно. Научитесь читать план выполнения, а затем применяйте наиболее важные исправления с помощью измерений «до» и «после» на основе реальной таблицы из миллиона строк.
- Начните с плана выполнения. Он говорит вам, что на самом деле делает база данных.
- Найдите полное сканирование больших таблиц, а затем добавьте индексы, соответствующие вашим фильтрам и соединениям.
- Избегайте переноса индексированного столбца в функцию, так как это может помешать эффективному использованию индекса.
- Измеряйте до и после, потому что каждая база данных и набор данных ведут себя по-разному.
Запрос, который в прошлом году занимал миллисекунды, сегодня может занять минуты просто потому, что таблица выросла. Оптимизация SQL-запросов — это не столько хитрые трюки, сколько повторяемый процесс: выясните, что делает база данных, удалите ненужную работу и проверьте, помогло ли это.
Мы протестировали каждый приведенный ниже метод на одном миллионе сгенерированных строк в SQLite 3.50. Тайминги — лучшие из нескольких запусков с одного ноутбука с использованием базы данных в памяти. Они не подойдут вашей системе, а PostgreSQL, MySQL и SQL Server имеют свои собственные оптимизаторы и форматы планов. Сосредоточьтесь на размере каждого улучшения и на принципах, лежащих в его основе.
Результаты с первого взгляда
| Техника | До | После |
|---|---|---|
| Индекс в столбце фильтра | 73 мс | 0,01 мс |
| Диапазон, а не функция в столбце | 96 мс | 33 мс |
| Составной индекс для двух фильтров | 19 мс | 2,2 мс |
| Набор клавиш вместо глубокого смещения | 8,1 мс | 0,01 мс |
Тестовая установка
CREATE TABLE customers (
id INTEGER PRIMARY KEY, name TEXT, city TEXT
);
CREATE TABLE orders (
id INTEGER PRIMARY KEY, customer_id INT, status TEXT,
created TEXT, total INT, note TEXT
);
-- 50,000 customers and 1,000,000 orders with random values
Простой процесс оптимизации
- Найдите важные запросы. Используйте журналы медленных запросов или мониторинг. Запрос длительностью 200 мс, выполняемый тысячу раз в минуту, может иметь большее значение, чем 10-секундный ежемесячный отчет.
- Прочитайте план. Посмотрите, что на самом деле делает база данных.
- Измените одну вещь. Добавьте индекс или перепишите часть запроса.
- Измерьте еще раз на реалистичных данных. План на 100 тестовых строк мало что скажет о миллионе.
- Следите за развитием событий. Планы могут меняться по мере роста данных и изменения статистики.
Прочитать план выполнения
План выполнения — это пошаговая стратегия базы данных для выполнения запроса, в том числе, какие индексы она использует и в каком порядке она объединяет таблицы. Префикс запроса, чтобы увидеть его:
| База данных | Команда |
|---|---|
| SQLite | ОБЪЯСНИТЕ ПЛАН ЗАПРОСА ВЫБЕРИТЕ... |
| PostgreSQL | ОБЪЯСНИТЬ АНАЛИЗИРОВАТЬ ВЫБРАТЬ... |
| MySQL | EXPLAIN SELECT ... или EXPLAIN ANALYZE |
| SQL-сервер | Фактический план выполнения в SSMS |
Обратите внимание, что EXPLAIN ANALYZE в PostgreSQL действительно запускает запрос, поэтому будьте осторожны при использовании его с UPDATE или DELETE. Вот что нужно искать в первую очередь:
| Вы видите | Значение | Обычно |
|---|---|---|
| Сканирование или последовательное сканирование | Читает всю таблицу | Проблемы с большими столами |
| Поиск или поиск по индексу | Переход к совпадающим строкам | Хорошо |
| Индекс покрытия | Ответил только из индекса | Очень хорошо |
| Временное B-дерево или сортировка | Дополнительная работа по сортировке | Стоит проверить |
Полное сканирование не является автоматически плохим. Если для запроса требуется большая часть небольшой таблицы, сканирование может оказаться самым быстрым вариантом. В PostgreSQL EXPLAIN ANALYZE также сравниваются предполагаемые строки с фактическими строками. Большая разница часто означает, что статистика таблицы устарела.
Добавьте правильный индекс
Этот запрос находит заказы одного клиента:
SELECT id, total FROM orders WHERE customer_id = 123;
Перед добавлением индекса планировалось полное сканирование:
SCAN orders
-- 20 rows in 73 ms
Затем мы добавили индекс в столбец фильтра:
CREATE INDEX idx_orders_customer ON orders(customer_id);
SEARCH orders USING INDEX idx_orders_customer (customer_id=?)
-- 20 rows in 0.01 ms
Те же 20 строк возвращались в тысячи раз быстрее, потому что база данных больше не читала миллион строк, чтобы найти их. Никакая другая техника в этой статье не дала нам большего выигрыша. Хорошими первыми кандидатами являются столбцы, используемые в WHERE, JOIN и ORDER BY, особенно когда они сужают результаты до нескольких строк. Наше руководство по индексам SQL объясняет, как они работают.
Не переносите индексированные столбцы в функции
Вот два способа найти мартовские заказы с индексом created:
-- Function on the column
SELECT id FROM orders WHERE substr(created, 1, 7) = '2026-03';
-- SCAN orders USING COVERING INDEX idx_orders_created
-- 84,961 rows in 96 ms
-- Plain range
SELECT id FROM orders
WHERE created >= '2026-03-01' AND created < '2026-04-01';
-- SEARCH orders USING COVERING INDEX idx_orders_created (created>? AND created<?)
-- 84,961 rows in 33 ms
Оба возвращают одинаковые строки, но первый занял примерно в три раза больше времени. План показывает, почему: при наличии функции в столбце база данных не может перейти к позиции в отсортированном индексе, поэтому ей приходится проходить SCAN через каждую запись. Версия диапазона может SEARCH прямо в нужное место. Условие, которое может использовать индекс таким образом, называется sargable.
Та же проблема возникает со следующими распространенными шаблонами:
| Избегайте | Предпочитаю |
|---|---|
ГДЕ ГОД(создан) = 2026 |
ГДЕ создано >= '2026-01-01' И создано < '2027-01-01' |
ГДЕ цена * 2 > 100 |
ГДЕ цена > 50 |
ГДЕ НИЖНИЙ(электронная почта) = 'a@b.com' |
Индекс на основе функций или параметры сортировки без учета регистра. |
ГДЕ имя НРАВИТСЯ '%99' |
Префиксный поиск или полнотекстовый поиск |
Последнее мы тоже проверили. Создается ведущий подстановочный знак SCAN customers, поскольку индекс, отсортированный по первой букве, не может помочь с совпадением в конце.
Составные индексы
Когда запрос фильтруется по двум столбцам, индекс по одному столбцу выполняет лишь часть работы:
SELECT id FROM orders
WHERE status = 'paid'
AND created >= '2026-03-01' AND created < '2026-03-08';
-- Using only the created index: 6,198 rows in 19 ms
CREATE INDEX idx_status_created ON orders(status, created);
-- SEARCH orders USING COVERING INDEX idx_status_created
-- (status=? AND created>? AND created<?)
-- 6,198 rows in 2.2 ms
Порядок столбцов имеет большое значение. Индекс на (status, created) работает как телефонная книга, отсортированная по фамилии, а затем по имени. Вы можете найти только фамилию, но не только имя. Наш запрос только к status мог бы использовать этот индекс. Фильтрация только по created обычно не может эффективно использовать его. Как правило, сначала помещайте столбцы, проверенные на равенство, а затем — столбцы диапазона.
В этом плане также говорится покрытие индекса, что означает, что индекс содержит все необходимое для запроса, поэтому саму таблицу не нужно читать. Выбор только тех столбцов, которые вам нужны, делает это более вероятным, что является еще одной причиной избегать SELECT *.
Более быстрая нумерация страниц
Использование OFFSET для глубоких страниц — это скрытые затраты, поскольку базе данных все равно приходится проходить мимо всех пропущенных строк:
-- Page deep into the results
SELECT id FROM orders ORDER BY id LIMIT 20 OFFSET 500000;
-- 8.1 ms
-- Keyset pagination: continue from the last id seen
SELECT id FROM orders WHERE id > 500000 ORDER BY id LIMIT 20;
-- 0.01 ms
Пагинация набора ключей остается быстрой независимо от того, насколько глубоко вы погружаетесь. Это также позволяет избежать смещения строк между страницами при добавлении новых данных. Компромисс заключается в том, что пользователи не могут сразу перейти к 5000-й странице, что редко является реальной необходимостью. В таблицах с широкими строками или с большим количеством строк, которые нужно пропустить, разрыв может быть намного больше, чем в нашем тесте.
Совет. Наши тайминги измеряют один запрос за раз на простаивающем компьютере. При реальной нагрузке неэффективный запрос наносит больший ущерб, поскольку он также удерживает блокировки и конкурирует за память, диск и ЦП со всем остальным.
Пишите более компактные запросы
- Выбирайте только те столбцы, которые вам нужны.
SELECT *отправляет больше данных и может помешать индексу покрыть запрос. - Ранняя фильтрация. Используйте
WHEREдля удаления строк перед группировкой иHAVINGтолько для условий агрегатов. См. SQL GROUP BY и HAVING. - Используйте LIMIT, если вам нужно всего несколько строк.
- Предпочитайте UNION ALL, если вам не нужно удалять дубликаты. Наш тест UNION vs UNION ALL показывает, какую экономию это дает.
- Избегайте ненужных DISTINCT. Часто скрывается соединение, создающее дубликаты.
- Используйте EXISTS для проверки существования. Она может остановиться при первом совпадении, как объясняется в нашем руководстве по подзапросам SQL.
- Следите за N+1 запросами. Реальной проблемой часто является один запрос на строку в цикле, обычно вызванный кодом приложения. Одно соединение или пакетный запрос могут заменить сотни обращений туда и обратно.
Присоединяется
Индексируйте столбцы, к которым вы присоединяетесь. Мы подготовили отчет об общих расходах для клиентов в одном городе, и план оказался именно таким, как вы и ожидали:
SELECT c.name, SUM(o.total)
FROM customers c
JOIN orders o ON o.customer_id = c.id
WHERE c.city = 'Goa'
GROUP BY c.id;
-- SCAN c
-- SEARCH o USING COVERING INDEX idx_cover (customer_id=?)
-- 9,900 rows in 34 ms
Он сканирует клиентов, а затем использует индекс для поиска заказов каждого из них. Без индекса по orders.customer_id базе данных пришлось бы выполнять гораздо больше работы для каждого клиента. Индекс внешнего ключа — одно из наиболее распространенных и ценных дополнений, которые вы можете сделать. Чтобы освежить ваше понимание основ, см. Объяснение объединений SQL.
Когда индексы обходятся вам дорого
Индексы не бесплатны, поэтому не добавляйте их для каждого столбца:
- Запись медленнее. Каждая вставка, обновление и удаление также должны обновлять каждый индекс.
- Больше места для хранения и памяти. Индексы могут увеличиваться в размерах в больших таблицах.
- Небольшая польза от неселективных столбцов. Индекс для истинного или ложного столбца может не помочь, если большинство строк совпадают.
- Избыточность. Индекс в
(a)часто не нужен, если он у вас уже есть в(a, b).
Периодически проверяйте статистику использования и удаляйте индексы, которые ничего не используют. И сохраняйте актуальность статистики с помощью ANALYZE или эквивалента вашей базы данных, потому что оптимизатор полагается на них при выборе хорошего плана. Иногда медленная часть — это спор, а не запрос. Длительные транзакции, удерживающие блокировки, могут сделать быстрый запрос медленным.
Распространенные ошибки
- Оптимизация без измерений. Многие уверенные предположения оказываются ошибочными.
- Тестирование на небольших объемах данных. Планы и сроки резко меняются по мере роста таблиц.
- Доверяем совету для другой базы данных. Советы для одного движка могут быть неприменимы к другому.
- Добавление индексов вслепую. Каждый из них тормозит запись.
- Игнорирование эффекта первого запуска. Кэши ускоряют второй запуск, поэтому запускайте его несколько раз.
Итоги
Большинство медленных запросов имеют обычные причины: отсутствующий индекс, функция в столбце или слишком много извлекаемых данных. Возьмите свой самый медленный реальный запрос на этой неделе, запустите для него EXPLAIN и найдите полное сканирование большой таблицы. Исправьте что-то, измерьте еще раз и запишите, что вы изменили.
Часто задаваемые вопросы
Что такое оптимизация SQL-запросов?
Это процесс, позволяющий запросам использовать меньше времени и ресурсов, обычно путем проверки планов выполнения, добавления подходящих индексов и переписывания неэффективных запросов.
Что такое план выполнения?
Это выбранная базой данных стратегия выполнения запроса, включая то, как она читает таблицы, какие индексы она использует и в каком порядке она объединяется.
Как найти медленные запросы?
Включите журнал медленных запросов вашей базы данных или используйте такие инструменты, как pg_stat_statements, в PostgreSQL. Затем сосредоточьтесь на запросах с наибольшим общим временем.
Всегда ли добавление индекса ускоряет запросы?
Нет. Это помогает выборочному чтению, но замедляет запись и использует хранилище. Оптимизатор также может игнорировать это условие, если большинство строк соответствуют условию.
SELECT * плохо влияет на производительность?
Это может быть. Он передает ненужные данные и может помешать индексу покрыть запрос. Обычно лучше перечислить только те столбцы, которые вам нужны.
Продолжайте учиться
Нужна помощь с тестированием, WordPress или SEO?
Мы помогаем командам выпускать лучшее программное обеспечение и развивать свои сайты. Расскажите нам, над чем вы работаете, и мы предложим четкий следующий шаг.
Больше руководств по тестирование, искусственный интеллект и современные разработки
Понравилась эта статья? Выберите тему и сразу приступайте к нашим новейшим руководствам.
Объяснение галлюцинаций искусственного интеллекта: почему языковые модели все выдумывают и как их уменьшить
Галлюцинации ИИ объяснили: что это такое, почему языковые модели их создают, распространенные типы, как уменьшить их с помощью заземления и подсказо…
Читать статью →DevOpsОбъяснение переменных среды: файлы .env, секреты и правильно выполненная конфигурация
Переменные среды объясняются на примерах Python, которые мы запускали: их чтение и установка, почему каждое значение является строкой, файлы .env, н…
Читать статью →Разработка ПООбъяснение ограничения скорости API: алгоритмы, заголовки и обработка ошибок 429
Ограничение скорости API объясняется с помощью проведенного нами моделирования: сегмент токенов, фиксированное окно, скользящее окно, 429 ответов, з…
Читать статью →Автоматизация тестированияИздевательство в Python: unittest.mock, патч и ошибки, из-за которых тесты лгут
Издевательство на Python с помощью unittest.mock, протестировано: Mock и return_value, Side_effect, исправление использования имени, спецификация и …
Читать статью →Тестирование ПООбъяснение покрытия кода: покрытие линий или ветвей и что на самом деле означает 100%
Покрытие кода объяснено с помощью реального запуска покрытия.py: покрытие строк, ветвей и условий, чтение отчета, почему 100%-ное покрытие все еще м…
Читать статью →Базы данных и SQLDELETE, TRUNCATE и DROP в SQL: различия, откат и когда использовать каждый из них
Объяснение DELETE, TRUNCATE и DROP на примере протестированного SQL: что каждый из них удаляет, откат, триггеры, сброс идентификаторов, скорость и ч…
Читать статью →Базы данных и SQLОбъяснение представлений SQL: создавайте, используйте и избегайте ловушек, с примерами
Представления SQL, объясненные с помощью запросов, которые мы выполняли: создание представления, результаты в реальном времени, скрытие столбцов, пр…
Читать статью →Разработка ПОИнтерфейс TypeScript и тип: реальные различия, протестированные с помощью компилятора
Интерфейс TypeScript против типа, проверенный реальным компилятором: что могут делать оба, что может делать только один, слияние объявлений, расшире…
Читать статью →Разработка ПООбъяснение Python *args и **kwargs: гибкие функции с понятными примерами
Python *args и **kwargs, объясненные с помощью кода, который мы запускали: упаковка и распаковка, порядок параметров, аргументы только по ключевым с…
Читать статью →Разработка ПОЛямбда-функции Python: синтаксис, реальное использование и когда их не следует использовать
Лямбда-функции Python, объясненные с помощью кода, который мы запускали: синтаксис, сортировка с помощью ключа, карты и фильтра, замыкания, ловушка …
Читать статью →Искусственный интеллектЧто такое ИИ-агенты? Как они работают: можно запустить простой цикл агента
Что такое агенты ИИ? Простое руководство по циклу агента, инструментам, памяти и ограничениям, с небольшим циклом Python, который мы запустили, реал…
Читать статью →DevOpsМониторинг и наблюдаемость: реальная разница с журналами, метриками и трассировками
Объяснение мониторинга и наблюдаемости: известные и неизвестные сбои, журналы, метрики и трассировки, пошаговое руководство по инцидентам при оформл…
Читать статью →DevOpsDocker Volumes против Bind Mounts: правильное сохранение данных контейнера
Объяснение томов Docker и монтирования привязки: почему исчезают данные контейнера, именованные тома, монтирование привязки, tmpfs, примеры создания…
Читать статью →Автоматизация тестированияTDD против BDD: ключевые различия, одна функция, созданная для обоих способов, и когда использовать каждый
TDD и BDD объясняются с помощью одной функции скидки, созданной в обоих направлениях: красно-зеленый рефакторинг с кодом, который мы запускали, сцен…
Читать статью →Тестирование ПОПользовательское приемочное тестирование (UAT): процесс, контрольный список и реальные примеры
Приемочное тестирование пользователей объяснило: кто его проводит, чем оно отличается от контроля качества, семиэтапный процесс, шаблон тестового сц…
Читать статью →Базы данных и SQLОбъяснение значений NULL в SQL: IS NULL, COALESCE, NULLIF и ловушки, которых следует избегать
Значения SQL NULL объяснены с помощью запросов, которые мы выполнили: трехзначная логика, IS NULL, COALESCE, NULLIF, как агрегаты, соединения и сорт…
Читать статью →Базы данных и SQLОператор SQL CASE WHEN: синтаксис, реальные примеры и распространенные ошибки
SQL CASE WHEN объяснен с помощью запросов, которые мы выполняли: простые формы и формы для поиска, порядок условий, повороты с помощью SUM, трюки CO…
Читать статью →Разработка ПОЧто такое JWT? Веб-токены JSON, объясненные на рабочем примере
Что такое JWT? Объяснение JSON Web Tokens: три части: токен, созданный и измененный в коде, который мы запускали, JWT и сеансы, хранилище, токены об…
Читать статью →Разработка ПООбъяснение цикла событий JavaScript: стек вызовов, микрозадачи и таймеры с примерами
Цикл событий JavaScript объясняется с помощью кода, который мы запускали: стек вызовов, очереди задач и микрозадач, почему setTimeout 0 не является …
Читать статью →Разработка ПОГенераторы Python и объяснение доходности: экономьте память с помощью реальных примеров
Генераторы Python и доходность, объясненные с помощью кода, который мы запускали: как они приостанавливаются и возобновляются, измеряют экономию пам…
Читать статью →Искусственный интеллектЧто такое вложения? Простое объяснение векторов и косинусного сходства
Что такое вложения? Простое руководство по векторам, косинусному подобию и семантическому поиску с небольшим примером, который мы использовали, общи…
Читать статью →DevOpsСине-зеленое и канареечное развертывание: различия, компромиссы и как выбрать
Объяснение сине-зеленого и канареечного развертывания: как каждый из них работает, стоимость, риски и откат, стабильное группирование пользователей,…
Читать статью →Автоматизация тестированияНенадежные тесты: что их вызывает и как их исправить навсегда
Ненадежные тесты объясняются на демонстрациях, которые мы запускали: основные причины, способы подтверждения и диагностики, правильные исправления в…
Читать статью →Тестирование ПОНагрузочное тестирование и стресс-тестирование: различия, метрики и примеры k6
Объяснение нагрузочного и стресс-тестирования: что доказывает каждое из них, тесты на всплески и выдержки, важные метрики, почему средние значения в…
Читать статью →Тестирование ПОТестовый пример и тестовый сценарий: ключевые различия, примеры и когда использовать каждый
Объяснение тестового случая и тестового сценария: четкие определения, параллельная таблица, одна функция сброса пароля, взятая из сценариев в случаи…
Читать статью →Базы данных и SQLОптимизация SQL-запросов: чтение планов выполнения и исправление медленных запросов с указанием времени
Оптимизация SQL-запросов проверена на миллионе строк: читайте планы выполнения, добавляйте правильные индексы, исправляйте неразмещаемые фильтры, ис…
Читать статью →Базы данных и SQLSQL UNION против UNION ALL: различия, примеры и проверка производительности
SQL UNION и UNION ALL объяснены с помощью запросов, которые мы выполнили: дубликаты, правила, которым следуют оба, реальная ошибка данных, измеренна…
Читать статью →Разработка ПОУчебное пособие по API JavaScript Fetch: GET, POST, обработка ошибок и тайм-ауты
Учебное пособие по API JavaScript Fetch, протестированное на локальном сервере: GET и POST, почему не выдается ошибка 404, многоразовый помощник, ст…
Читать статью →Разработка ПООбработка файлов Python: чтение, запись, CSV, JSON и pathlib с примерами
Обработка файлов Python объясняется с помощью кода, который мы запускали: открытые режимы, чтение больших файлов, CSV, JSON, pathlib, двоичные файлы…
Читать статью →Разработка ПОКлассы и объекты Python: учебник ООП с реальными примерами
Классы и объекты Python, объясненные с помощью кода, который мы запускали: __init__, методы, атрибуты класса и экземпляра, наследование, свойства, м…
Читать статью →Искусственный интеллектЧто такое большая языковая модель? Как работают LLM, объяснено без шумихи
Что такое большая языковая модель? LLM объясняется простым языком: токены, встраивания, внимание, обучение, температурные и контекстные окна, крошеч…
Читать статью →DevOpsКоманды Linux для начинающих: основное руководство по терминалу с примерами
Команды Linux для начинающих, сгруппированные по задачам: навигация, файлы, просмотр журналов, grep, каналы, разрешения, процессы и архивы, с практи…
Читать статью →Автоматизация тестированияSelenium vs Playwright: ключевые различия, сравнение кода и что выбрать
Сравнение Selenium и Playwright: архитектура, ожидание, поддержка браузера и языка, отладка, одинаковый тест в обоих инструментах, советы по миграци…
Читать статью →Тестирование ПОРазделение эквивалентности: метод проектирования тестов, объясненный на рабочих примерах
Объяснение эквивалентного разделения: как найти действительные и недействительные разделы, рабочие примеры для возрастов, паролей и купонов, проведе…
Читать статью →Тестирование ПОСерьезность и приоритет в тестировании программного обеспечения: различия, матрица и реальные примеры
Объяснение серьезности и приоритета при тестировании программного обеспечения: четкие определения, четырехсторонняя матрица с примерами, шкалы уровн…
Читать статью →Базы данных и SQLУчебное пособие по подзапросам SQL: типы, коррелирующие подзапросы и EXISTS с примерами
Руководство по подзапросам SQL с выполненными нами запросами: скалярные подзапросы, IN, FROM и SELECT, коррелированные подзапросы, EXISTS, ловушка N…
Читать статью →Базы данных и SQLОбъяснение транзакций SQL и ACID: COMMIT, ROLLBACK и уровни изоляции
Транзакции SQL и ACID, объясненные с помощью банковского перевода, который мы выполнили: COMMIT, ROLLBACK, точки сохранения, блокировки, уровни изол…
Читать статью →Разработка ПОGit Commands Cheat Sheet: The Commands You Actually Use, With Examples
Шпаргалка по командам Git, сгруппированная по задачам: настройка, промежуточный этап, ветки, удаленные устройства, тайник, история и исправление оши…
Читать статью →Разработка ПООбъяснение промисов в JavaScript: then, catch, Promise.all и распространенные ошибки
Обещания JavaScript, объясненные с помощью кода, который мы запускали: состояния, цепочки then и catch, обработка ошибок, Promise.all, allSettled, R…
Читать статью →Разработка ПОУчебное пособие по словарю Python: методы, примеры и общие шаблоны
Учебное пособие по словарю Python с кодом, который мы выполнили: создание, чтение и обновление словарей, ключевые методы, слияние, понимание, шаблон…
Читать статью →Искусственный интеллектЧто такое РАГ? Генерация с расширенным поиском, объясненная на рабочем примере
Что такое РАГ? Retrieval-augmented generation explained step by step: indexing, chunking, embeddings, retrieval, a small working Python example, eva…
Читать статью →DevOpsУчебное пособие по Terraform для начинающих: инфраструктура как код от первого файла до модулей
Учебное пособие по Terraform для начинающих: начните без облачной учетной записи, изучите инициализацию, планирование и применение, затем переменные…
Читать статью →DevOpsDocker и Kubernetes: ключевые различия, как они работают вместе и что вам нужно
Объяснение Docker и Kubernetes: что делает каждый из них, одно и то же приложение работает с обоими, сравнение Docker Compose и Swarm, изменение doc…
Читать статью →Автоматизация тестированияУчебное пособие по Pytest для начинающих: фикстуры, параметризация и реальные примеры
Учебное пособие по pytest для начинающих с тестами, которые мы запускали на pytest 9.2: утверждения, фикстуры, параметризация, conftest, маркеры, tm…
Читать статью →Тестирование ПОЖизненный цикл тестирования программного обеспечения (STLC): 6 этапов, критерии входа и выхода, пример
Объясняется жизненный цикл тестирования программного обеспечения: шесть этапов STLC с критериями входа и выхода, результаты, пример проработанной фу…
Читать статью →Разработка ПОGit merge vs rebase: отличия, примеры и когда что использовать
Git merge vs rebase с реальным выводом log, сравнительной таблицей, золотым правилом rebase и безопасным рабочим процессом для команды.
Читать статью →Разработка ПОГенераторы списков в Python: синтаксис, примеры и когда их избегать
Генераторы списков в Python: синтаксис, фильтры, if-else, вложенные циклы, измеренное время и случаи, когда обычный цикл for лучше.
Читать статью →Базы данных и SQLSQL JOIN: объяснение с примерами (Inner, Left, Right, Full)
Разберите SQL JOIN шаг за шагом на примерах таблиц и запросов: INNER, LEFT, RIGHT, FULL, CROSS и SELF, а также частые ошибки и советы по производите…
Читать статью →