2. Почему начинаем с БД
• БД есть практически во всех бизнес
приложениях и не только (in process db)
• С проектирования БД проще всего начать
проектирование корпоративного
приложения (хотя это, быть может, и не
лучший способ)
– Альтернативный путь (DDD) – существенно
более сложен и рискован (требует большей
квалификации)
3. Что такое БД и зачем они нужны
• Коллекция структурированных данных
– большого их количества
• Цель БД – упростить операции с данными:
– хранение данных
– доступ к данным
4. Задачи решаемые БД
• Как организовать данные (логическая схема
хранения)
• Как хранить данные (физическая схема
хранения)
• Как считывать данные (быстро!!)
• Атомарность операций с данными
• Согласованность (консистентность) данных
• Изоляция пар-льных операций над данными
• Надежность хранения данных в случае сбоев
• Контроль доступа к данным
5. Правильное восприятие
• БД это черный ящик и набор некоторых
правил, при соблюдении которых, он
хорошо решает вышеуказанные проблемы
• Какие правила нужно знать
– Как организовывать данные (лог. структура)
– Как их запрашивать
– Основы физ. устройства (индексы, для пр-сти)
– Что такое транзакции, блокировки и как они
работают
6. Основные типы БД
• On-line transaction processing (OLTP)
– Многочисленные изменения небольших кусков
данных, быстрые и относительно
многочисленные update / insert
• On-line analytical data processing
– «Тяжелые запросы» агрегированных
объединенных данных, не обязательно
актуальных, редкие, но массовые insert /
update
7. NoSQL движение
• Основная проблема scalability
– Традиционные БД в силу архитектуры очень
плохо горизонтально масштабируются
• Добавляем уменьшенные требования
(noACID) и другие проблемы (ООП)
получаем массу решений
– Google, Facebook, Amazon…
– http://nosql-database.org/
9. Логическая организация данных
• Ученые много думали, спорили и решили:
• Таблица (набор колонок и ограничений на них)
– Колонка (тип данных + размер)
• Ограничения (в т.ч. на уникальность)
– Колонка
• Первичный ключ
– Колонка
• Внешний ключ (ссылка на первичный ключ
устанавливающее обязательное отношение между
таблицами / строками)
10. Нормализация (искл. дублирования)
• Почему? Потому что научно обоснованно
Студент
Оценка
Группа
Id группы Студент
Название Оценка
группы ГруппаId
Студент Id оценки
ОценкаId Положительная
ГруппаId / отрицательная
11. ERD Диаграммы
• Рисуют заранее что бы не мучаться в процессе
• Ключевое – сущность. То, с чем система работает.
– Чем управляет
– Оперирует как объектом, понятием
– У чего есть идентификатор
• 1-* : FK NOT NULL
• 0..1 - *: FK NULL
• *..* -> Таблица связка
12. SQL: язык запросов к лог. модели
• Декларативный язык описания того, чего
хочется от БД
• Стандарт (SQL 92 / 99)
– Однако, как обычно, каждый реализовал по
своему
• В зависимости от БД разные наборы доп.
конструкций (функции, процедуры, циклы,
переменные и пр.). T/SQL, PL/SQL
13. Все что нужно знать об SQL*
SELECT [DISTINCT]
[TOP (выражение)]
<список колонок> (выражений / подзапросов)
[ FROM { <таблицы / подзапросы> } [ ,...n ] ]
[ WHERE <условия, в т.ч. с подзапросами>]
[ GROUP BY <{колонка / выражение }> [ ,...n ]]
[ HAVING <условия для аггрегатов> ]
[ ORDER BY { колонка / выражение } [ ,...n ] ]
* фраза приведена исключительно в рекламных целях
15. Сложный select
SELECT [t0].[Id], [t0].[UserName], [t0].[Password], [t0].[TempPassword], [t0].[TempPasswordEmail], [t0].[TempPasswordMobilePhone], [t0].[UserType], [t0].[Email], [t0].[IsEmailConfirmed],
[t0].[EmailToBeConfirmed], [t0].[MobilePhone], [t0].[IsMobilePhoneConfirmed], [t0].[MobilePhoneToBeConfirmed], [t0].[MobilePhoneConfirmationCode], [t0].[IsBlocked], [t0].[IsDeleted],
[t0].[RowVersion], [t0].[LastName], [t0].[FirstName], [t0].[MiddleName], [t0].[Sex], [t0].[BirthDate], [t0].[HomePhone], [t0].[HasAgreedToAdvertisement], [t0].[MobileRegionId], [t0].[OperatorId],
[t0].[CityId], [t0].[PostAddressId], [t0].[DoesRequireMobileInfoUpdate], [t0].[RequestToDeleteDateTime], [t0].[RequestToDeleteChannel], [t16].[test], [t16].[Id] AS [Id2], [t16].[PostIndex],
[t16].[RegionId], [t16].[RayonId], [t16].[CityId] AS [CityId2], [t16].[StreetId], [t16].[House], [t16].[IsEstate], [t16].[Building], [t16].[Stroenie], [t16].[Flat], [t16].[IsOffice], [t16].[Comments],
[t16].[IsCorrect], [t16].[RowVersion] AS [RowVersion2], [t16].[Id2] AS [Id3], [t16].[TypeId], [t16].[Name], [t16].[DisplayName], [t16].[OrderNum], [t16].[UtcOffset], [t16].[FederalRegionId],
[t16].[Id3] AS [Id4], [t16].[FullName], [t16].[ShortName], [t16].[DisplayName2], [t16].[OrderNum2], [t16].[test2], [t16].[Id4] AS [Id5], [t16].[RegionId2], [t16].[TypeId2], [t16].[Name2],
[t16].[ContainsRegionCapitol], [t16].[IsVerified], [t16].[Id22] AS [Id6], [t16].[FullName2], [t16].[ShortName2], [t16].[DisplayName3], [t16].[OrderNum3], [t16].[Id5] AS [Id7], [t16].[RegionId3],
[t16].[RayonId2], [t16].[TypeId3], [t16].[Name3], [t16].[Status], [t16].[OrderNum4], [t16].[UtcOffset2], [t16].[IsVerified2], [t16].[StreetRequired], [t16].[Id6] AS [Id8], [t16].[TypeId4], [t16].[Name4],
[t16].[DisplayName4], [t16].[OrderNum5], [t16].[UtcOffset3], [t16].[FederalRegionId2], [t16].[Id7] AS [Id9], [t16].[FullName3], [t16].[ShortName3], [t16].[DisplayName5], [t16].[OrderNum6],
[t16].[test3], [t16].[Id8] AS [Id10], [t16].[RegionId4], [t16].[TypeId5], [t16].[Name5], [t16].[ContainsRegionCapitol2], [t16].[IsVerified3], [t16].[Id23] AS [Id11], [t16].[FullName4],
[t16].[ShortName4], [t16].[DisplayName6], [t16].[OrderNum7], [t16].[test4], [t16].[Id9] AS [Id12], [t16].[CityId2] AS [CityId3], [t16].[TypeId6], [t16].[Name6], [t16].[IsVerified4], [t16].[Id24] AS
[Id13], [t16].[FullName5], [t16].[ShortName5], [t16].[DisplayName7], [t16].[OrderNum8]
FROM [dbo].[Users] AS [t0]
LEFT OUTER JOIN (
SELECT 1 AS [test], [t1].[Id], [t1].[PostIndex], [t1].[RegionId], [t1].[RayonId], [t1].[CityId], [t1].[StreetId], [t1].[House], [t1].[IsEstate], [t1].[Building], [t1].[Stroenie], [t1].[Flat], [t1].[IsOffice],
[t1].[Comments], [t1].[IsCorrect], [t1].[RowVersion], [t2].[Id] AS [Id2], [t2].[TypeId], [t2].[Name], [t2].[DisplayName], [t2].[OrderNum], [t2].[UtcOffset], [t2].[FederalRegionId], [t3].[Id] AS [Id3],
[t3].[FullName], [t3].[ShortName], [t3].[DisplayName] AS [DisplayName2], [t3].[OrderNum] AS [OrderNum2], [t6].[test] AS [test2], [t6].[Id] AS [Id4], [t6].[RegionId] AS [RegionId2], [t6].[TypeId] AS
[TypeId2], [t6].[Name] AS [Name2], [t6].[ContainsRegionCapitol], [t6].[IsVerified], [t6].[Id2] AS [Id22], [t6].[FullName] AS [FullName2], [t6].[ShortName] AS [ShortName2], [t6].[DisplayName] AS
[DisplayName3], [t6].[OrderNum] AS [OrderNum3], [t7].[Id] AS [Id5], [t7].[RegionId] AS [RegionId3], [t7].[RayonId] AS [RayonId2], [t7].[TypeId] AS [TypeId3], [t7].[Name] AS [Name3], [t7].[Status],
[t7].[OrderNum] AS [OrderNum4], [t7].[UtcOffset] AS [UtcOffset2], [t7].[IsVerified] AS [IsVerified2], [t7].[StreetRequired], [t8].[Id] AS [Id6], [t8].[TypeId] AS [TypeId4], [t8].[Name] AS [Name4],
[t8].[DisplayName] AS [DisplayName4], [t8].[OrderNum] AS [OrderNum5], [t8].[UtcOffset] AS [UtcOffset3], [t8].[FederalRegionId] AS [FederalRegionId2], [t9].[Id] AS [Id7], [t9].[FullName] AS
[FullName3], [t9].[ShortName] AS [ShortName3], [t9].[DisplayName] AS [DisplayName5], [t9].[OrderNum] AS [OrderNum6], [t12].[test] AS [test3], [t12].[Id] AS [Id8], [t12].[RegionId] AS
[RegionId4], [t12].[TypeId] AS [TypeId5], [t12].[Name] AS [Name5], [t12].[ContainsRegionCapitol] AS [ContainsRegionCapitol2], [t12].[IsVerified] AS [IsVerified3], [t12].[Id2] AS [Id23],
[t12].[FullName] AS [FullName4], [t12].[ShortName] AS [ShortName4], [t12].[DisplayName] AS [DisplayName6], [t12].[OrderNum] AS [OrderNum7], [t15].[test] AS [test4], [t15].[Id] AS [Id9],
[t15].[CityId] AS [CityId2], [t15].[TypeId] AS [TypeId6], [t15].[Name] AS [Name6], [t15].[IsVerified] AS [IsVerified4], [t15].[Id2] AS [Id24], [t15].[FullName] AS [FullName5], [t15].[ShortName] AS
[ShortName5], [t15].[DisplayName] AS [DisplayName7], [t15].[OrderNum] AS [OrderNum8]
FROM [dbo].[PostAddresses] AS [t1]
INNER JOIN ([dbo].[Regions] AS [t2]
INNER JOIN [dbo].[ObjectTypes] AS [t3] ON [t3].[Id] = [t2].[TypeId]) ON [t2].[Id] = [t1].[RegionId]
LEFT OUTER JOIN (
SELECT 1 AS [test], [t4].[Id], [t4].[RegionId], [t4].[TypeId], [t4].[Name], [t4].[ContainsRegionCapitol], [t4].[IsVerified], [t5].[Id] AS [Id2], [t5].[FullName], [t5].[ShortName], [t5].[DisplayName],
[t5].[OrderNum]
FROM [dbo].[Rayons] AS [t4]
INNER JOIN [dbo].[ObjectTypes] AS [t5] ON [t5].[Id] = [t4].[TypeId]
) AS [t6] ON [t6].[Id] = [t1].[RayonId]
INNER JOIN ([dbo].[Cities] AS [t7]
INNER JOIN ([dbo].[Regions] AS [t8]
INNER JOIN [dbo].[ObjectTypes] AS [t9] ON [t9].[Id] = [t8].[TypeId]) ON [t8].[Id] = [t7].[RegionId]
LEFT OUTER JOIN (
SELECT 1 AS [test], [t10].[Id], [t10].[RegionId], [t10].[TypeId], [t10].[Name], [t10].[ContainsRegionCapitol], [t10].[IsVerified], [t11].[Id] AS [Id2], [t11].[FullName], [t11].[ShortName],
[t11].[DisplayName], [t11].[OrderNum]
FROM [dbo].[Rayons] AS [t10]
INNER JOIN [dbo].[ObjectTypes] AS [t11] ON [t11].[Id] = [t10].[TypeId]
) AS [t12] ON [t12].[Id] = [t7].[RayonId]) ON [t7].[Id] = [t1].[CityId]
LEFT OUTER JOIN (
SELECT 1 AS [test], [t13].[Id], [t13].[CityId], [t13].[TypeId], [t13].[Name], [t13].[IsVerified], [t14].[Id] AS [Id2], [t14].[FullName], [t14].[ShortName], [t14].[DisplayName], [t14].[OrderNum]
FROM [dbo].[Streets] AS [t13]
16. Физическая схема хранения
• Таблица – представляем как плоский фаил
• Кластерный индекс
– Физически сортирует таблицу (соотв. один)
– Используется как ссылка на запись в других
индексах (и FK)
• Для ускорения запросов (поисков) – обычные
индексы
– Чаще всего: b-деревья, но могут быть и другие
– Ключ (колонка или неск.) и «включенные колонки»
17. Простой практический совет
• Используйте суррогатные, возрастающие
(IDENTITY) первичные ключи и кластерные
индексы
– Гарантированно уникальны (!)
– Единообразно и просто в понимании
– Экономят размер (особенно на др. индексах)
– Увеличивают производительность в большинстве
случаев
• http://sqlskills.com/BLOGS/KIMBERLY/category/C
lustering-Key.aspx
18. Оптимизация запросов
• Перезапись SQL (реляционная алгебра)
– Раскрыть подзапросы
– Переставить и раскрыть логические операторы
–…
• Выбор методов выполнения (на осн. эвристик,
или статистических оценок)
– Алгоритмы доступа: scan / seek и откуда
– Алгоритмы сортировки / join’а (nested loops, merge,
hash)
• Все это – план запроса
– Планы - кэшируются
19. Например
• Разные варианты стратегий join’а
– Nested loops
– Merge
– Hash
• Зачем нужны включенные в индекс
колонки
20. 6 План запроса
5
• Позволяет видеть решения оптимизатора
3
SELECT COUNT(*)
2
FROM PrizesWon as pw 1
INNER JOIN Prizes AS prizes ON prizes.Id = pw.PrizeId
WHERE (pw.OrderId IS NOT NULL) AND (pw.PrizeType = 'Payment') AND (pw.UserId =
544496) AND (prizes.ActionName = 'NCP 2011 Baltika23')
4
3 1
6
5 2
4
22. Требования к транзакциям (ACID)
• Atomic (атомарность): все или ничего
• Durable (надежность): если коммит, то
навсегда
• Consistency (консистентность): соблюдаются
ограничения логической схемы
– Все три надежно и прозрачно обеспечиваются
реализацией БД
• Isolation (изоляция): дает правильные
результаты при любых параллельных
транзакциях
23. Параллелизм: два подхода
• Пессимистический параллелизм
– Обеспечивается блокировками
запрашиваемого ресура (остальные ждут)
• Оптимистический параллелизм
– Обеспечивается версиями (или проверкой всех
полей), т.е. через обнаружение конфликтов
26. Уровни изоляций и проблемы
Сотрудник Отдел Зарплата
Иван Обувной 10К
Александр Обувной 15К
Олеся Игрушек 12К
Ира Игрушек 8К
Вася Обувной 14К
T1: всем в обувном поднять ЗП на 10%
T2: Переместить Олесю и Иру в обувной
• Результат д.б. аналогичный
последовательному выполнению операций
(в любом порядке)
27. Решение
• Разделяем на маленькие кусочки (в БД
чаще всего строки) и блокируем на время
транзакции всё что мы трогаем. Держим
блокировки до конца транзакции
• Для оптимизации можно использовать R/W
блокировки
По этому поводу можно встретить термин двухфазное
блокирование – если не хотите писать БД – не вдавайтесь в
детали.
28. Проблемы
• Гранулярность накладываемых блокировок
– Select avg(зарплата)
– Эскалации
• Что делать если не получается получить лок
– Ждать (таймаут)
• Дедлоки.T1:lock(a), T2:lock(b), T1:locl(b),
T2:lock(a)
– Проверять и выбирать жертву или таймаут
– Повтор выполнения (возможен голод)
– Блокировать только все сразу, вперед или в одном
порядке (нереально)
29. Еще проблемы
Сотрудник Отдел Зарплата
Иван Обувной 10К
Александр Обувной 15К
Олеся Игрушек 12К
Ира Игрушек 8К
Вася Обувной 14К
T1: всем в обувном поднять ЗП на 10%
T2: Переместить Олесю и Иру в обувной
• Даже если блокировать все строки, новые записи
могут попасть под условие (во время scan)
– Range locks (Index) / TABLE locks. И то и то – очень
грустно (WHERE IS NULL, верхушка индекса)
30. Пессимистическое решение
• Не мешать OLTP с OLAP
• Ждать
• Подбирать уровни изоляции и допускать
ошибки
– Read uncommitted (без блокировок, только
атомарность)
– Read committed (R временно, W до конца)
– Repeatable read (W, R до конца на строки)
– Serializable (W, R до конца + Range locks)
31. Оптимистическое решение (2)
• Изоляция на основе версий
(оптимистический параллелизм)
• Легко гарантирует согласованное чтение
• Проблемы с записью (при конфликте –
откат транзакции)
• Исследования показали что кроме крайних
случаев менее эффективно чем
блокировки, хотя как опция –
поддерживается в современных БД
32. Восстановление и резервирование
• Full / incremental backup
• Журнал транзакций
• Целостность данных на физическом уровне
• Различные стратегии mirror / репликации
для дублирования в realtime / построения
схем master / slave
33. Распространенные БД
• MySQL
– OS, простая, популярная, куплена oracle
• PostgreSql
– OS, более взрослая и сложная
• Oracle
– Enterprise АД, очень дорого и мощно
• MS SQL Server
– Серьезный продукт с человеческим лицом
34. MS SQL Server (Demo)
• Enterprise Studio
– Intellisense
– План запроса
• Books online
• SQL Server profiler
• Tuning advisor
35. Общие советы разработчикам
• До последнего полагайтесь на базу данных в
– Производительности выборок
– Сохранении консистентности данных
– Оптимизации запросов
– Блокировках и обеспечении параллелизма
– Резервном копировании
• Почему? Потому что их писали очень умные
люди очень много лет
– Отказ от БД – только после измерения реальной
производительности (тест / прототип)
36. Ресурсы
• SQL Server books online
– http://msdn.microsoft.com/en-
us/library/ms130214.aspx
– http://www.microsoft.com/sqlserver/en/us/ed
itions/express.aspx
• Wikipedia
• Произвольная книга по нужной вам СУБД
• http://softwarestencils.com/ (visio stencils)
37. Темы для докладов
• AOP
• Kanban / Lean
• SCRUM: Team / ScrumMaster – подробнее
про процесс (DS, Retro, SprintPlan, Demo…)
• Portfolio management, BMG (Alex Ostervald),
Scrum of Scrum
• NoSql БД
38. Лабы
• Открытые данные
– http://www.apps4russia.ru/, http://apps4russia.reformal.ru/,
http://data.worldbank.org/
• Готовое:
– http://minenergo.gov.ru/activity/statistic/,http://www.fms.gov.ru/abo
ut/ofstat/, http://www.federalspace.ru/main.php?id=10,
http://ivan.begtin.name/2011/10/02/gosuslugijson/
• Повышенный балл:
– Или наличие БД
– Или наличие веб интерфейса
– Индивидуальное задание (для тех, у кого уже есть что показать)
• Стажировка (Тестер / Разработчик)
– MS: C#, MS MVC, MS SQL Server