Подход Доктора Хауса к тестированию оптимизации
запросов(пятая серия)
Автор: Михалев Сергейf1incode.com
Это я
Team Lead / Software Developer in VIAcode
www.linkedin.com/in/ssmikhalev
vk.com/ssmikhalev
f1incode.com
У вас есть отличная команда
Но не докторов, а программистов,которые занимаются оптимизацией
вашего приложения.
Воскресенье
Только они думают: “Какого черта стакан в два раза больше,
чем нужно!”
Все-таки тестировщики
особенные люди.
Почему?!
Я думаю, из меня выйдет
хороший тестировщик.
Я замечательно
умею всё ломать!
Лучше занимайся
своим делом!
Понедельник: на этой неделе я буду тестировщиком
Понедельник
На этой недели я буду
тестировщиком!
Понедельник
Понедельник Ладно, разбирайтесь сами. Вот вам новый кейс!
И постарайтесь сделать так, чтобы Хаус
ничего не нашел!
Анализ кейса: дифференциальный анализ
У нас серьезно замедлилась
страница диагнозов.
Возможно, дело в
функции list_diagnosis
Понедельник: подготовка к тестированию
Нужна серьезная подготовка к тестированию производительности …
Обработка запросов
Запрос1. Разбирает запрос2. Оценивает окружение3. Анализирует
распределение данных 4. Строит эффективный
план запроса5. Выполняет запрос
Данные
Вывод: оптимизация очень сильно зависит от конкретных условий выполнения.
Подготовка к тестированию производительности запросов
Цель – быть как можно “ближе” к реальному окружению.Необходимо:1. Проконтролировать одинаковость
тестового и реального окружений.2. Сверить совпадение схем баз данных.3. Собрать достаточное количество реальных
запросов.4. Подготовить процесс запуска запросов и
сбора метрик.
Подготовка: 1 - тестовое окружение
Необходимо проверить:1. Что тестовый сервер как можно ближе к
“реальному”: CPU, жесткий диск, RAID-ы, оперативная память.
2. Совпадение операционных систем, обновлений.
3. Настройки СУБД: версия, сколько памяти выделено, на какие диски смонтированы базы, collation-ы.
Подготовка: 2 - база данных1. Проверить совпадение схем баз данных: одинаковость индексов, функций, статистики, collation.
2. Данные должны быть близкие к реальным. Нет никакого смысла тестировать производительность запросов на тестовых (смоделированных) данных.
Подготовка: 3 - запросы
Запрос
Запрос
1. Необходимо использовать только запросы от реальных пользователей.
2. Количество запросов должно быть достаточным.
Подготовка: 4 - процесс запускаЦель - получать контролируемые результаты для их дальнейшего анализа.
Необходимо создавать как можно более стабильную из теста в тест нагрузку. Поэтому важно контролировать:1. Порядок запуска запросов (иначе возможны
серьезные расхождения в результатах из-за разных закешированных планов запроса).
2. Создаваемую нагрузку (количество
параллельно запускаемых запросов).
Выводы1. Обязательно контролировать, что тестируемые
сервера обладают сравнимой с продакшеном производительностью.
2. Нет большого смысла тестировать оптимизацию на смоделированных данных.
3. Необходимо стремиться воспроизводить как можно более похожую на реальную нагрузку.
4. Если вы проигнорировали или не обеспечили хотя бы один из подготовительных шагов – вашим тестам нельзя доверять.
Вечер понедельника
Всё ли я предусмотрел?
Всё ли подготовил?
Вторник
Мы исправили
кейс!!
Стало быстрее в
10 раз!!
Реакция Хауса
Особенно программисты
Поэтому ВСЁ нужно перепроверять.
Экспресс анализ измененийСтарая функция Новая функция
Запускаем тестовые трейсы
запросов
Анализ результатов: метрики
1. Время выполнения запроса.2. Количество логических чтений.3. Время СУБД на обработку запроса.4. Количество памяти, выделенное на
обработку запроса.
Анализ результатов
В 3 раза
меньше
CPU В 8 раз
быстрее
В 2 раза
меньше
ридов
Вырос
максимум
Анализ результатов: распределение по времени выполнения.
Главный пик сместился, т.е большинство запросов стало быстрее.
Но появился новый пик, которого раньше не было.
Возвращаем кейс
Выводы1. Практически невозможно оптимизировать
запрос так, чтобы не замедлить что-то другое.
2. Обычно нет проблем оптимизировать один проблемный запрос. Наибольшая сложность - оптимизировать весь набор запросов.
3. Поэтому - чем более универсальный запрос, тем он медленнее!
4. Это первый из “балансов”. Можно оптимизировать какой-то конкретный запрос за счет других.
Вечер вторника
Среда
Идет активная работа.
И только тестировщик Хаус в это время …
Среда
Команда находит и представляет новое решение.
Экспресс анализ измененийСтарая функция Новая функция
Куда исчезла логика?
Экспресс анализ измененийcreate view dbo.v_diagnosis_clusteredwith schemabinding asselect g.diagnosis_id, g.patient_id, g.desease_name, g.create_time, d.doctor_id, d.hospital_id, d.doctor_namefrom DIAGNOSIS ginner join DOCTOR d on g.doctor_id = d.doctor_id
select …from PATIENT pcross apply( select top 1 desease_name, doctor_name from V_DIAGNOSIS_CLUSTERED g where g.patient_id = p.patient_id and g.hospital_id = @hospital_id order by g.create_time) d
select …from PATIENT pcross apply( select top 1 desease_name, doctor_name from DIAGNOSIS g inner join DOCTOR d on g.doctor_id = d.doctor_id where g.patient_id = p.patient_id and d.hospital_id = @hospital_id order by g.create_time) d
create unique clustered index clustered_index on dbo.v_diagnosis_clustered(hospital_id, patient_id)
Старая версия Новая версия
View vs Indexed View
1. Виртуальная (логическая) таблица, представляющая собой поименованный запрос.
2. Физически данные не хранятся. SELECT вычисляется каждый раз, когда к нему обращаются.
View Indexed View
1. Представление, на котором создан кластерный индекс.
2. Физически данные хранятся, как и в обычной таблице.
Баланс скорости чтения и скорости модификаций
1. Кластерное представление будет пересчитываться при каждой модификации исходных таблиц.
2. Модификация станет медленнее, а чтение, скорее всего, быстрее.
3. Баланс №2 – оптимизация скорости чтения за счет скорости модификаций или наоборот.
Анализ результатов: чтений
В 3 раза
меньше
CPU В 8 раз
быстрее
В 2 раза
меньше
ридов
Максимум
в 1.5 раза
меньше
Анализ результатов: модификаций
Вырос
CPU
Увеличился
максимум
Выросло
время Выросли
чтения
Анализ результатов
Выносить или нет …
Еще разок …
Намного лучше. А
можно сделать еще лучше?
Выводы1. Наиболее важный баланс в оптимизации
запросов – это баланс скорости чтений и скорости модификаций.
2. Практически всегда можно ускорить чтения, замедлив соответствующие изменения данных.
3. Принимать решения о приемлемости такой оптимизации необходимо, основываясь на знаниях о приложении.
Четверг
Опять идет активная работа.
Четверг
Новое решение …
Экспресс анализ измененийСтарая функция Новая функция
Они одинаковые!!!
Значит, изменилась
схема базы!!!
Индексы?!
Индексы: кучаextent
Inde
x Al
loca
tion
Map extent
extent
create table DOCTOR( doctor_id int identity(1,1) not null, hospital_id int not null, first_name nvarchar(50) not null, last_name nvarchar(50) not null, create_time datetime not null)
Так как нет кластерного индекса, очевидно, что
данные в куче неупорядоченные.
Table Scan
Table Scan
Table Scan
Индексы: кластерный индексALTER TABLE DOCTOR
ADD CONSTRAINT PK_DOCTOR
PRIMARY KEY CLUSTERED
(
doctor_id asc
)
Data Rows
264 …
… …
312 …
Data Rows
210 …
… …
263 …
Data Rows
157 …
… …
209 …
Data Rows
104 …
… …
156 …
Data Rows
53 …
… …
103 …
Data Rows
1 …
… …
52 …
Index Rows
157
210
264
Index Rows
1
53
104
Index Rows
1
157
Root
Intermediate Level
Leaf / Data Level
На листовых уровнях хранятся значения всех столбцов
Определяет физический порядок даных, поэтому может быть создан только однин кластерный индекс на таблице
Все индексы организованы как B-Tree
CREATE NONCLUSTERED INDEX IX_HOSPITAL ON DOCTOR( hospital_id)
Data Rows
264 …
… …
312 …
Data Rows
210 …
… …
263 …
Data Rows
157 …
… …
209 …
Data Rows
104 …
… …
156 …
Data Rows
53 …
… …
103 …
Data Rows
1 …
… …
52 …
Root
Intermediate Level
Leaf Level
Index Rows1
25
Index Rows51
75
Index Rows1
51
Index Rows1
…
24
1
...
104
Index Rows25
…
50
100
...
209
Index Rows51
…
74
106
...
202
Index Rows75
…
83
264
...
210
Clus
tere
d In
dex
Тоже организован как B-Tree
Не задает физический порядок хранения данных в таблице, а сортирует данные в каком-то порядке
Содержит копии данных из таблицы
На листовом уровне содержатся ссылки на кластерный индекс
Индексы: некластерный индекс
Представляйте себе книгу
Кластерный индекс – это
номера страниц в
книге.
Некластерный индекс – это предметный
указатель.
Анализ результатов: добавление индексов
В 3 раза
меньше
CPU В 4 раз
быстрее
Меньше
чтений
Анализ результатов: добавление индексов - модификация
Немного
медленнее
Выводы1. Изменения индексов – наиболее
популярный и простой способ оптимизации.
2. Индексы, как и кластерные представления, замедляют операции модификации.
3. Обычно функциональное тестирование не требуется.
Пятница
Совместный анализ всех результатов
Анализ результатов
Выросший максимум
Скорость функции
Скорость модификаций
Выносим изменения
Выводы1. Для любой задачи существует несколько
путей и подходов оптимизации.2. Оптимизация запросов – это всегда
вопрос баланса, поэтому задача тестирования - правильно выявить этот баланс.
3. Выбор того или иного решения всегда зависит от специфики приложения.
Выводы недели1. Подготовка к тестированию – самый
важный этап. Если вы проигнорировали хотя бы один из подготовительных шагов – вашим тестам нельзя доверять.
2. Оптимизация – это вопрос баланса:• оптимизация какого-то конкретного
запроса за счет других;• оптимизация чтений за счет
модификаций;3. Поэтому почти всегда можно найти, что в
действительности стало медленнее.
Молодцы!!!
Помощь
Командная работа или тестировщиков нужно всегда поддерживать!!!
Подводим итоги недели1) Разобрались с операциями над
множествами, такими как except и union. И даже реализовали except all.
2) Мы разработали метод функционального тестирования запросов.
3) Нашли очень замысловатую логическую ошибку и исправили старый функциональный баг.
Подход Доктора Хауса к тестированию оптимизации запросов
1. Разбираться в проблеме до конца.
2. Быть одной командой.
3. Все врут, а значит - всё нужно перепроверять.
4. Не бояться резать по живому, но всегда контролировать.
5. Не сдаваться!!!
Вопросы?
Team Lead / Software Developer in VIAcode
www.linkedin.com/in/ssmikhalev
vk.com/ssmikhalev
f1incode.com