vault backup: 2024-06-17 18:42:04
This commit is contained in:
parent
675dc36dc0
commit
99966062c4
33
.obsidian/graph.json
vendored
33
.obsidian/graph.json
vendored
@ -6,7 +6,36 @@
|
||||
"hideUnresolved": false,
|
||||
"showOrphans": true,
|
||||
"collapse-color-groups": true,
|
||||
"colorGroups": [],
|
||||
"colorGroups": [
|
||||
{
|
||||
"query": "path:wiki/zero ",
|
||||
"color": {
|
||||
"a": 1,
|
||||
"rgb": 13730816
|
||||
}
|
||||
},
|
||||
{
|
||||
"query": "path:knowledge/dev ",
|
||||
"color": {
|
||||
"a": 1,
|
||||
"rgb": 9582847
|
||||
}
|
||||
},
|
||||
{
|
||||
"query": "path:knowledge/health ",
|
||||
"color": {
|
||||
"a": 1,
|
||||
"rgb": 8767232
|
||||
}
|
||||
},
|
||||
{
|
||||
"query": "path:",
|
||||
"color": {
|
||||
"a": 1,
|
||||
"rgb": 5431378
|
||||
}
|
||||
}
|
||||
],
|
||||
"collapse-display": true,
|
||||
"showArrow": false,
|
||||
"textFadeMultiplier": 0,
|
||||
@ -17,6 +46,6 @@
|
||||
"repelStrength": 10,
|
||||
"linkStrength": 1,
|
||||
"linkDistance": 250,
|
||||
"scale": 0.2539867059356025,
|
||||
"scale": 0.26588896145134355,
|
||||
"close": false
|
||||
}
|
8
.obsidian/hotkeys.json
vendored
8
.obsidian/hotkeys.json
vendored
@ -374,13 +374,5 @@
|
||||
],
|
||||
"key": "]"
|
||||
}
|
||||
],
|
||||
"app:delete-file": [
|
||||
{
|
||||
"modifiers": [
|
||||
"Mod"
|
||||
],
|
||||
"key": "Backspace"
|
||||
}
|
||||
]
|
||||
}
|
20
.obsidian/plugins/home-tab/data.json
vendored
20
.obsidian/plugins/home-tab/data.json
vendored
@ -24,24 +24,24 @@
|
||||
"unresolvedLinks": false,
|
||||
"recentFilesStore": [
|
||||
{
|
||||
"filepath": "Home.md",
|
||||
"timestamp": 1718301876022
|
||||
"filepath": "_inbox/Кэширование.md",
|
||||
"timestamp": 1718638803720
|
||||
},
|
||||
{
|
||||
"filepath": "knowledge/dev/Git.md",
|
||||
"timestamp": 1718300752762
|
||||
"filepath": "wiki/zero/00 HighLoad.md",
|
||||
"timestamp": 1718638801082
|
||||
},
|
||||
{
|
||||
"filepath": "knowledge/dev/Скрипты для Git.md",
|
||||
"timestamp": 1718300748508
|
||||
"filepath": "knowledge/human/Стресс.md",
|
||||
"timestamp": 1718638580710
|
||||
},
|
||||
{
|
||||
"filepath": "wiki/people/Алекс Корб.md",
|
||||
"timestamp": 1718300621374
|
||||
"filepath": "_inbox/Репликация в MySQL.md",
|
||||
"timestamp": 1718638377453
|
||||
},
|
||||
{
|
||||
"filepath": "wiki/Полис ОМС.md",
|
||||
"timestamp": 1718300607145
|
||||
"filepath": "_inbox/Репликация master-master.md",
|
||||
"timestamp": 1718638184942
|
||||
}
|
||||
],
|
||||
"starredFileStore": [],
|
||||
|
6
.obsidian/plugins/obsidian-git/data.json
vendored
6
.obsidian/plugins/obsidian-git/data.json
vendored
@ -1,7 +1,7 @@
|
||||
{
|
||||
"commitMessage": "vault backup: {{date}}",
|
||||
"commitDateFormat": "YYYY-MM-DD HH:mm:ss",
|
||||
"autoSaveInterval": 0,
|
||||
"autoSaveInterval": 5,
|
||||
"autoPushInterval": 0,
|
||||
"autoPullInterval": 0,
|
||||
"autoPullOnBoot": false,
|
||||
@ -18,12 +18,12 @@
|
||||
"treeStructure": false,
|
||||
"refreshSourceControl": true,
|
||||
"basePath": "",
|
||||
"differentIntervalCommitAndPush": false,
|
||||
"differentIntervalCommitAndPush": true,
|
||||
"changedFilesInStatusBar": false,
|
||||
"showedMobileNotice": true,
|
||||
"refreshSourceControlTimer": 7000,
|
||||
"showBranchStatusBar": true,
|
||||
"setLastSaveToLastCommit": false,
|
||||
"setLastSaveToLastCommit": true,
|
||||
"submoduleRecurseCheckout": false,
|
||||
"gitDir": "/Users/struchkov/Documents/Backup/obsidian_sadtech",
|
||||
"showFileMenu": true,
|
||||
|
376
.obsidian/plugins/recent-files-obsidian/data.json
vendored
376
.obsidian/plugins/recent-files-obsidian/data.json
vendored
@ -1,9 +1,197 @@
|
||||
{
|
||||
"recentFiles": [
|
||||
{
|
||||
"basename": "Кэширование",
|
||||
"path": "_inbox/Кэширование.md"
|
||||
},
|
||||
{
|
||||
"basename": "00 HighLoad",
|
||||
"path": "wiki/zero/00 HighLoad.md"
|
||||
},
|
||||
{
|
||||
"basename": "Стресс",
|
||||
"path": "knowledge/human/Стресс.md"
|
||||
},
|
||||
{
|
||||
"basename": "Репликация в MySQL",
|
||||
"path": "_inbox/Репликация в MySQL.md"
|
||||
},
|
||||
{
|
||||
"basename": "Репликация master-master",
|
||||
"path": "_inbox/Репликация master-master.md"
|
||||
},
|
||||
{
|
||||
"basename": "CAP теорема",
|
||||
"path": "_inbox/CAP теорема.md"
|
||||
},
|
||||
{
|
||||
"basename": "Репликация master-slave",
|
||||
"path": "_inbox/Репликация master-slave.md"
|
||||
},
|
||||
{
|
||||
"basename": "Олег Чирухин",
|
||||
"path": "wiki/people/Олег Чирухин.md"
|
||||
},
|
||||
{
|
||||
"basename": "Home",
|
||||
"path": "Home.md"
|
||||
},
|
||||
{
|
||||
"basename": "Disaster recovery",
|
||||
"path": "_inbox/Disaster recovery.md"
|
||||
},
|
||||
{
|
||||
"basename": "Репликация БД",
|
||||
"path": "_inbox/Репликация БД.md"
|
||||
},
|
||||
{
|
||||
"basename": "Журнал БД",
|
||||
"path": "_inbox/Журнал БД.md"
|
||||
},
|
||||
{
|
||||
"basename": "Reliability",
|
||||
"path": "_inbox/Reliability.md"
|
||||
},
|
||||
{
|
||||
"basename": "High Availability",
|
||||
"path": "_inbox/High Availability.md"
|
||||
},
|
||||
{
|
||||
"basename": "Репликация",
|
||||
"path": "_inbox/Репликация.md"
|
||||
},
|
||||
{
|
||||
"basename": "Шардирование",
|
||||
"path": "_inbox/Шардирование.md"
|
||||
},
|
||||
{
|
||||
"basename": "Настройка репликации в PostgreSQL",
|
||||
"path": "_inbox/Настройка репликации в PostgreSQL.md"
|
||||
},
|
||||
{
|
||||
"basename": "Репликация в PostgreSQL",
|
||||
"path": "_inbox/Репликация в PostgreSQL.md"
|
||||
},
|
||||
{
|
||||
"basename": "Оптимизация SQL запросов",
|
||||
"path": "_inbox/Оптимизация SQL запросов.md"
|
||||
},
|
||||
{
|
||||
"basename": "JOIN SQL",
|
||||
"path": "_inbox/JOIN SQL.md"
|
||||
},
|
||||
{
|
||||
"basename": "Индекс в PostgreSQL",
|
||||
"path": "_inbox/Индекс в PostgreSQL.md"
|
||||
},
|
||||
{
|
||||
"basename": "Составные индексы в PostgreSQL",
|
||||
"path": "_inbox/Составные индексы в PostgreSQL.md"
|
||||
},
|
||||
{
|
||||
"basename": "00 PostgreSQL",
|
||||
"path": "wiki/zero/00 PostgreSQL.md"
|
||||
},
|
||||
{
|
||||
"basename": "PgBouncer",
|
||||
"path": "_inbox/PgBouncer.md"
|
||||
},
|
||||
{
|
||||
"basename": "IN SQL",
|
||||
"path": "_inbox/IN SQL.md"
|
||||
},
|
||||
{
|
||||
"basename": "00 SQL",
|
||||
"path": "wiki/zero/00 SQL.md"
|
||||
},
|
||||
{
|
||||
"basename": "Explain в PostgreSQL",
|
||||
"path": "_inbox/Explain в PostgreSQL.md"
|
||||
},
|
||||
{
|
||||
"basename": "Индексы в MySQL",
|
||||
"path": "_inbox/Индексы в MySQL.md"
|
||||
},
|
||||
{
|
||||
"basename": "Профилирование запросов в PostgreSQL",
|
||||
"path": "knowledge/dev/database/Профилирование запросов в PostgreSQL.md"
|
||||
},
|
||||
{
|
||||
"basename": "pg_stat_statements",
|
||||
"path": "pg_stat_statements.md"
|
||||
},
|
||||
{
|
||||
"basename": "Доклад. Индексы в PostgreSQL. Как понять, что создавать",
|
||||
"path": "source/доклады/Доклад. Индексы в PostgreSQL. Как понять, что создавать.md"
|
||||
},
|
||||
{
|
||||
"basename": "Обучающий курс от HighLoad конференции 2024",
|
||||
"path": "source/курсы/_toc/Обучающий курс от HighLoad конференции 2024.md"
|
||||
},
|
||||
{
|
||||
"basename": "Memcached",
|
||||
"path": "_inbox/Memcached.md"
|
||||
},
|
||||
{
|
||||
"basename": "00 Nginx",
|
||||
"path": "wiki/zero/00 Nginx.md"
|
||||
},
|
||||
{
|
||||
"basename": "Explain в MySQL",
|
||||
"path": "_inbox/Explain в MySQL.md"
|
||||
},
|
||||
{
|
||||
"basename": "Extended keys MySQL",
|
||||
"path": "_inbox/Extended keys MySQL.md"
|
||||
},
|
||||
{
|
||||
"basename": "ORDER BY",
|
||||
"path": "knowledge/dev/database/ORDER BY.md"
|
||||
},
|
||||
{
|
||||
"basename": "Архитектура MySQL",
|
||||
"path": "Архитектура MySQL.md"
|
||||
},
|
||||
{
|
||||
"basename": "Идеи для ремонта",
|
||||
"path": "projects/Ремонт квартиры/Идеи для ремонта.md"
|
||||
},
|
||||
{
|
||||
"basename": "Предлоги в Английском",
|
||||
"path": "knowledge/english/Предлоги в Английском.md"
|
||||
},
|
||||
{
|
||||
"basename": "Index condition pushdown",
|
||||
"path": "_inbox/Index condition pushdown.md"
|
||||
},
|
||||
{
|
||||
"basename": "Покрывающий индекс",
|
||||
"path": "_inbox/Покрывающий индекс.md"
|
||||
},
|
||||
{
|
||||
"basename": "Составные индексы в MySQL",
|
||||
"path": "_inbox/Составные индексы в MySQL.md"
|
||||
},
|
||||
{
|
||||
"basename": "Составные индексы в БД",
|
||||
"path": "Составные индексы в БД.md"
|
||||
},
|
||||
{
|
||||
"basename": "Без названия",
|
||||
"path": "Без названия.md"
|
||||
},
|
||||
{
|
||||
"basename": "00 MySQL",
|
||||
"path": "wiki/zero/00 MySQL.md"
|
||||
},
|
||||
{
|
||||
"basename": "00 Linux",
|
||||
"path": "wiki/zero/00 Linux.md"
|
||||
},
|
||||
{
|
||||
"basename": "Ударение",
|
||||
"path": "_inbox/Ударение.md"
|
||||
},
|
||||
{
|
||||
"basename": "Git",
|
||||
"path": "knowledge/dev/Git.md"
|
||||
@ -11,194 +199,6 @@
|
||||
{
|
||||
"basename": "Скрипты для Git",
|
||||
"path": "knowledge/dev/Скрипты для Git.md"
|
||||
},
|
||||
{
|
||||
"basename": "Алекс Корб",
|
||||
"path": "wiki/people/Алекс Корб.md"
|
||||
},
|
||||
{
|
||||
"basename": "Полис ОМС",
|
||||
"path": "wiki/Полис ОМС.md"
|
||||
},
|
||||
{
|
||||
"basename": "Не переработано",
|
||||
"path": "source/Не переработано.md"
|
||||
},
|
||||
{
|
||||
"basename": "Книга",
|
||||
"path": "meta/templates/Книга.md"
|
||||
},
|
||||
{
|
||||
"basename": "Личная продуктивность 1",
|
||||
"path": "knowledge/productivity/Личная продуктивность 1.md"
|
||||
},
|
||||
{
|
||||
"basename": "Ежегодная проверка здоровья",
|
||||
"path": "checklists/Ежегодная проверка здоровья.md"
|
||||
},
|
||||
{
|
||||
"basename": "Киники",
|
||||
"path": "_inbox/Киники.md"
|
||||
},
|
||||
{
|
||||
"basename": "Заявление на АГС",
|
||||
"path": "archive/Мобилизация/Заявление на АГС.md"
|
||||
},
|
||||
{
|
||||
"basename": "Изучаю gRPC",
|
||||
"path": "source/доклады/Изучаю gRPC.md"
|
||||
},
|
||||
{
|
||||
"basename": "Про поветски",
|
||||
"path": "archive/Мобилизация/Про поветски.md"
|
||||
},
|
||||
{
|
||||
"basename": "containerd.io",
|
||||
"path": "_inbox/containerd.io.md"
|
||||
},
|
||||
{
|
||||
"basename": "Simple",
|
||||
"path": "knowledge/english/Simple.md"
|
||||
},
|
||||
{
|
||||
"basename": "Разработка",
|
||||
"path": "knowledge/dev/Разработка.md"
|
||||
},
|
||||
{
|
||||
"basename": "Дополнительные материалы по Java",
|
||||
"path": "source/доклады/Дополнительные материалы по Java.md"
|
||||
},
|
||||
{
|
||||
"basename": "JOIN",
|
||||
"path": "knowledge/dev/database/JOIN.md"
|
||||
},
|
||||
{
|
||||
"basename": "Docker compose для запуска socks5",
|
||||
"path": "knowledge/dev/Docker compose для запуска socks5.md"
|
||||
},
|
||||
{
|
||||
"basename": "Полезное про собеседования",
|
||||
"path": "notes/Полезное про собеседования.md"
|
||||
},
|
||||
{
|
||||
"basename": "Сезонные фрукты и овощи",
|
||||
"path": "wiki/Сезонные фрукты и овощи.md"
|
||||
},
|
||||
{
|
||||
"basename": "Заметки по ТЗ 4",
|
||||
"path": "archive/Я.Практикум/Полезное/Заметки по ТЗ 4.md"
|
||||
},
|
||||
{
|
||||
"basename": "ConcurrentModificationException",
|
||||
"path": "archive/Я.Практикум/Полезное/ConcurrentModificationException.md"
|
||||
},
|
||||
{
|
||||
"basename": "Ежедневный чеклист",
|
||||
"path": "checklists/Ежедневный чеклист.md"
|
||||
},
|
||||
{
|
||||
"basename": "Использование нескольких репозиториев в проекте",
|
||||
"path": "archive/Я.Практикум/Полезное/Использование нескольких репозиториев в проекте.md"
|
||||
},
|
||||
{
|
||||
"basename": "Тимлид",
|
||||
"path": "_inbox/Тимлид.md"
|
||||
},
|
||||
{
|
||||
"basename": "Работа с архитектурой информационных систем в нашем изменчивом мире",
|
||||
"path": "source/доклады/Работа с архитектурой информационных систем в нашем изменчивом мире.md"
|
||||
},
|
||||
{
|
||||
"basename": "Looking Glass",
|
||||
"path": "knowledge/dev/network/Looking Glass.md"
|
||||
},
|
||||
{
|
||||
"basename": "Open System Interconnection Reference Model",
|
||||
"path": "knowledge/dev/network/Open System Interconnection Reference Model.md"
|
||||
},
|
||||
{
|
||||
"basename": "Нелинейная зависимость длительности от сложности задачи",
|
||||
"path": "source/цитаты/Нелинейная зависимость длительности от сложности задачи.md"
|
||||
},
|
||||
{
|
||||
"basename": "Mock конфигурация для Oauth2 SpringBoot",
|
||||
"path": "knowledge/dev/java/frameworks/spring/Mock конфигурация для Oauth2 SpringBoot.md"
|
||||
},
|
||||
{
|
||||
"basename": "Second Brain",
|
||||
"path": "knowledge/education/Second Brain.md"
|
||||
},
|
||||
{
|
||||
"basename": "Рекомендации к ТЗ 6",
|
||||
"path": "archive/Я.Практикум/Полезное/Рекомендации к ТЗ 6.md"
|
||||
},
|
||||
{
|
||||
"basename": "Ешки",
|
||||
"path": "knowledge/health/питание/Ешки.md"
|
||||
},
|
||||
{
|
||||
"basename": "At или in?",
|
||||
"path": "knowledge/english/At или in?.md"
|
||||
},
|
||||
{
|
||||
"basename": "Создание linux сервиса для приложения Spring Boot",
|
||||
"path": "knowledge/dev/java/snippets/Создание linux сервиса для приложения Spring Boot.md"
|
||||
},
|
||||
{
|
||||
"basename": "SponsorBlock",
|
||||
"path": "_inbox/SponsorBlock.md"
|
||||
},
|
||||
{
|
||||
"basename": "Мультимодульные проекты c Jandex",
|
||||
"path": "knowledge/dev/Мультимодульные проекты c Jandex.md"
|
||||
},
|
||||
{
|
||||
"basename": "excalibrain",
|
||||
"path": "excalibrain.md"
|
||||
},
|
||||
{
|
||||
"basename": "image (2)",
|
||||
"path": "meta/files/image (2).png"
|
||||
},
|
||||
{
|
||||
"basename": "2024-03-10 1710054825",
|
||||
"path": "_inbox/2024-03-10 1710054825.md"
|
||||
},
|
||||
{
|
||||
"basename": "Майнд-мэп",
|
||||
"path": "knowledge/productivity/Майнд-мэп.md"
|
||||
},
|
||||
{
|
||||
"basename": "Как оценить уровень финансовой свободы?",
|
||||
"path": "knowledge/economy/Как оценить уровень финансовой свободы?.md"
|
||||
},
|
||||
{
|
||||
"basename": "Сериализация и Десериализация даты в Jackson",
|
||||
"path": "knowledge/dev/java/snippets/Сериализация и Десериализация даты в Jackson.md"
|
||||
},
|
||||
{
|
||||
"basename": "Задача 24",
|
||||
"path": "notes/Собеседования/Задачи/Задача 24.md"
|
||||
},
|
||||
{
|
||||
"basename": "Семейная ипотека 6%",
|
||||
"path": "archive/Квартира/Семейная ипотека 6%.md"
|
||||
},
|
||||
{
|
||||
"basename": "Проект",
|
||||
"path": "knowledge/productivity/Проект.md"
|
||||
},
|
||||
{
|
||||
"basename": "Циклические зависимости сервисов",
|
||||
"path": "knowledge/dev/java/other/Циклические зависимости сервисов.md"
|
||||
},
|
||||
{
|
||||
"basename": "Приветственное сообщение",
|
||||
"path": "archive/Я.Практикум/Сообщения/Приветственное сообщение.md"
|
||||
},
|
||||
{
|
||||
"basename": "Настройки noteshare для Obsidian",
|
||||
"path": "notes/Настройки noteshare для Obsidian.md"
|
||||
}
|
||||
],
|
||||
"omittedPaths": [],
|
||||
|
@ -17,3 +17,4 @@ JOIN comments ON posts. id = comments.post_id
|
||||
```
|
||||
|
||||
Индекс по `posts.id` бесполезен. Индекс по `comments.post_id` обязателен.
|
||||
|
@ -16,4 +16,4 @@ CAP теорема — это принцип, описывающий фунда
|
||||
|
||||
Согласно теореме CAP, в любой момент времени система может обеспечивать только два из этих трёх свойств. Это означает, что при разработке системы приходится принимать компромисс между этими свойствами в зависимости от требований приложения и условий эксплуатации. Например, если для системы критически важна согласованность данных и её устойчивость к разделению, возможно придётся пожертвовать её доступностью в некоторых сценариях.
|
||||
|
||||
Google заявляет, что их продукт Spanner якобы нарушает CAP теорему.
|
||||
Google заявляет, что их продукт Google Spanner якобы нарушает CAP теорему.
|
@ -1,14 +1,15 @@
|
||||
---
|
||||
aliases:
|
||||
- DR
|
||||
tags:
|
||||
- зрелость/🌱
|
||||
date:
|
||||
- - 2024-03-05
|
||||
zero-link:
|
||||
- "[[00 HighLoad]]"
|
||||
parents: []
|
||||
parents:
|
||||
linked:
|
||||
---
|
||||
Восстановление после катастрофы.
|
||||
Восстановление после сбоев.
|
||||
|
||||
Потеря данных почти всегда
|
||||
Почти всегда происходит потеря данных.
|
32
_inbox/Explain в MySQL.md
Normal file
32
_inbox/Explain в MySQL.md
Normal file
@ -0,0 +1,32 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- зрелость/🌱
|
||||
date:
|
||||
- - 2024-06-16
|
||||
zero-link:
|
||||
- "[[00 MySQL]]"
|
||||
parents:
|
||||
linked:
|
||||
- "[[Explain в PostgreSQL]]"
|
||||
---
|
||||
![](Архитектура%20MySQL.md#^432879)
|
||||
|
||||
**Недостатки explain**. Многие связаны с работой оптимизатора.
|
||||
- Не учитывает хранимые функции
|
||||
- Может обмануть. И выполнение запроса будет отличаться от плана.
|
||||
- Мало информации: план совпадает, производительность нет. Одинаковые результаты для различных ситуаций
|
||||
- Выполнение from подзапросов
|
||||
- Может выполняться дольше, чем сам запрос
|
||||
|
||||
Пример выполнения
|
||||
![](Pasted%20image%2020240616122716.png)
|
||||
|
||||
Нужно обратить внимание на
|
||||
- type: ALL. Значит индексы не используются
|
||||
- type: eq_ref. Поиск по ключу
|
||||
- key. Это индекс, который был выбран.
|
||||
- key_len. Длина индекса, которая была использована в [составном](Составные%20индексы%20в%20MySQL.md)
|
||||
|
||||
## Дополнительные материалы
|
||||
- [Основы индексирования и возможности EXPLAIN в MySQL](https://highload.guide/blog/basics_indexing.html)
|
48
_inbox/Explain в PostgreSQL.md
Normal file
48
_inbox/Explain в PostgreSQL.md
Normal file
@ -0,0 +1,48 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- зрелость/🌱
|
||||
date:
|
||||
- - 2024-06-10
|
||||
zero-link:
|
||||
- "[[00 PostgreSQL]]"
|
||||
parents:
|
||||
- "[[Профилирование запросов в PostgreSQL]]"
|
||||
linked:
|
||||
- "[[Explain в MySQL]]"
|
||||
---
|
||||
Используя ключевое слово `EXPLAIN` перед запросом, можно получить детальную информацию о том, что **планирует** сделать PostgreSQL под капотом для выполнения запроса.
|
||||
|
||||
Пример выполнения explain
|
||||
```sql
|
||||
postgres=# explain select * from users where id=20;
|
||||
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------
|
||||
Index Scan using users_pkey on users (cost=0.15..8.17 rows=1 width=72)
|
||||
Index Cond: (id = 20)
|
||||
(2 rows)
|
||||
```
|
||||
|
||||
Можно изменить формат вывода. Например, можно вывести все в JSON.
|
||||
```sql
|
||||
explain(format json) select * from users where id=20;
|
||||
```
|
||||
|
||||
> [!NOTE] Analyze
|
||||
> Explain не выполняет запрос, поэтому результаты будут лишь приблизительными. Можно улучшить качество анализа, если добавить ключевое слово `explain analyze`, тогда explain также выполнит запрос.
|
||||
|
||||
PostgreSQL использует условные единицы обозначающие стоимость выполнения запроса - cost. Один cost это время, которое затрачивается на извлечение 1 блока размером 8 килобайт при Seq Scan. При этом обычно используется 2 значения. Первое означает сколько времени пройдет до начала первых результатов, а вторая когда вернется весь результат.
|
||||
|
||||
Если cost очень маленький, а actual time большое, это может означать, что есть проблемы со сбором статистики. Возможно выключен автовакуум?
|
||||
|
||||
Стоит найти самый дорогой узел запроса и оптимизировать его.
|
||||
|
||||
**Виды проходов по индексу:**
|
||||
- Seq Scan - последовательный просмотр таблицы. Худший вариант.
|
||||
- Index Scan - просмотр по индексу в таблице
|
||||
- Index Only Scan - был использован [Покрывающий индекс](Покрывающий%20индекс.md)
|
||||
- Bitmap Heap Scan - оптимизация с построением битовых карт для поиска. Сначала строятся битовые карты с использованием нескольких индексов, затем эти битовые карты комбинируются.
|
||||
|
||||
## Дополнительные материалы
|
||||
- [Производительность запросов в PostgreSQL / Илья Космодемьянский (PostgreSQL Consulting) - YouTube](https://www.youtube.com/watch?v=c-ySk8COI1c)
|
@ -1,37 +0,0 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- зрелость/🌱
|
||||
date:
|
||||
- - 2024-06-10
|
||||
zero-link:
|
||||
- "[[00 PostgreSQL]]"
|
||||
parents:
|
||||
- "[[Профилирование запросов в PostgreSQL]]"
|
||||
linked:
|
||||
---
|
||||
Используя ключевое слово `EXPLAIN` перед запросом, можно получить детальную информацию о том, что делает PostgreSQL под капотом для выполнения запроса, и что это ему стоит.
|
||||
|
||||
Пример выполнения
|
||||
```sql
|
||||
postgres=# explain select * from users where id=20;
|
||||
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------
|
||||
Index Scan using users_pkey on users (cost=0.15..8.17 rows=1 width=72)
|
||||
Index Cond: (id = 20)
|
||||
(2 rows)
|
||||
```
|
||||
|
||||
Можно изменить формат вывода. Например, можно вывести все в JSON.
|
||||
```sql
|
||||
explain(format json) select * from users where id=20;
|
||||
```
|
||||
|
||||
Explain не выполняет запрос, поэтому результаты будут лишь приблизительными. Можно улучшить качество анализа, если добавить ключевое слово `explain analyze`, тогда explain также выполнит запрос.
|
||||
|
||||
**Виды проходов по индексу:**
|
||||
- Seq Scan - последовательный просмотр таблицы. Худший вариант.
|
||||
- Index Scan - просмотр по индексу в таблице
|
||||
- Index Only Scan - был использован [Покрывающий индекс](Покрывающий%20индекс.md)
|
||||
- Bitmap Heap Scan - оптимизация с построением битовых карт для поиска. Сначала строятся битовые карты с использованием нескольких индексов, затем эти битовые карты комбинируются.
|
16
_inbox/Extended keys MySQL.md
Normal file
16
_inbox/Extended keys MySQL.md
Normal file
@ -0,0 +1,16 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- зрелость/🌱
|
||||
date:
|
||||
- - 2024-06-16
|
||||
zero-link:
|
||||
- "[[00 MySQL]]"
|
||||
parents:
|
||||
- "[[Индексы в MySQL]]"
|
||||
linked:
|
||||
---
|
||||
В MySQL термин "extended keys" относится к расширению использования индексов, введённому в MySQL 5.6, которое улучшает оптимизацию запросов. Расширенные ключи (extended keys) позволяют оптимизатору учитывать все колонки, используемые в запросе (в SELECT, WHERE, ORDER BY, GROUP BY и других частях запроса), для определения того, какой индекс будет наиболее эффективным для выполнения запроса.
|
||||
|
||||
Особенность ключей в InnoDB – это то, что вторичные ключи ссылаются на первичный ключ, поэтому фактически вторичный ключ в InnoDB представляет собой вторичный ключ + указатель на первичный ключ. Используется только для фильтрации строк.
|
||||
![](Pasted%20image%2020240616114457.png)
|
@ -11,20 +11,22 @@ zero-link:
|
||||
parents:
|
||||
linked:
|
||||
---
|
||||
High Availability (Высокая доступность). Отношение времени, когда сайт работал к общему времени. Исторически измеряется в 9-ках.
|
||||
High Availability (Высокая доступность). От ношение времени, когда сервис работал к общему времени.
|
||||
|
||||
Исторически измеряется в 9-ках.
|
||||
|
||||
| Доступность | Время простоя в год | Время простоя в месяц |
|
||||
| ---- | ---- | :--: |
|
||||
| 99% | 3.65 дней | 7.20 часов |
|
||||
| 99,5% | 1.83 дней | 3.60 часов |
|
||||
| 99,9% | 8.76 часов | 43.2 минут |
|
||||
| 99,95% | 4.38 часов | 21.56 минут |
|
||||
| 99,99% | 52.56 минут | 4.32 минут |
|
||||
| 99,99% | 5.26 минут | 25.9 секунд |
|
||||
| 99,9999% | 31.5 секунд | 2.59 секунд |
|
||||
| ----------- | ------------------- | :-------------------: |
|
||||
| 99% | 3.65 дней | 7.20 часов |
|
||||
| 99,5% | 1.83 дней | 3.60 часов |
|
||||
| 99,9% | 8.76 часов | 43.2 минут |
|
||||
| 99,95% | 4.38 часов | 21.56 минут |
|
||||
| 99,99% | 52.56 минут | 4.32 минут |
|
||||
| 99,999% | 5.26 минут | 25.9 секунд |
|
||||
| 99,9999% | 31.5 секунд | 2.59 секунд |
|
||||
|
||||
Что влияет на доступность?
|
||||
- Отказы и аварии. Чаще всего незапланированные. Техногенного или природного характера.
|
||||
- Отказы и аварии. Чаще всего не запланированные. Техногенного или природного характера.
|
||||
- Запланированные. Обновление ПО, которое невозможно выполнить без остановки.
|
||||
- [Reliability](Reliability.md)
|
||||
## Вопросы
|
||||
|
14
_inbox/IN SQL.md
Normal file
14
_inbox/IN SQL.md
Normal file
@ -0,0 +1,14 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- зрелость/🌱
|
||||
date:
|
||||
- - 2024-06-17
|
||||
zero-link:
|
||||
- "[[00 SQL]]"
|
||||
parents:
|
||||
linked:
|
||||
---
|
||||
## Проблемы производительности IN
|
||||
Длинный IN, который очень часто генерируют ORM. [Исправление](Pasted%20image%2020240617132439.png)
|
||||
![500](Pasted%20image%2020240617132203.png)
|
16
_inbox/Index condition pushdown.md
Normal file
16
_inbox/Index condition pushdown.md
Normal file
@ -0,0 +1,16 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- зрелость/🌱
|
||||
date:
|
||||
- - 2024-06-16
|
||||
zero-link:
|
||||
- "[[00 MySQL]]"
|
||||
parents:
|
||||
linked:
|
||||
---
|
||||
Мало что понял
|
||||
|
||||
![](Pasted%20image%2020240616113900.png)
|
||||
|
||||
- [Основы индексирования и расширенные возможности EXPLAIN в MySQL / Василий Лукьянчиков (Станигост) - YouTube](https://youtu.be/DFmdW5UwhjA?si=_cXgbvaVI5KUP2fv&t=1198)
|
29
_inbox/JOIN SQL.md
Normal file
29
_inbox/JOIN SQL.md
Normal file
@ -0,0 +1,29 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- зрелость/🌱
|
||||
date: 2024-02-05
|
||||
zero-link:
|
||||
- "[[00 SQL]]"
|
||||
parents:
|
||||
linked:
|
||||
---
|
||||
Postgres имеет три основных алгоритма Join'а, а именно
|
||||
- Nested Loop. Берем данные из одной таблицы и циклами их Join'им
|
||||
- Hash index. Одна, чаще маленькая, таблица хэшируется и по этому хэшу Join'ится с другой таблицей
|
||||
- Merge Join.
|
||||
|
||||
```sql
|
||||
SELECT * FROM posts WHERE author = "Peter"
|
||||
JOIN comments ON posts. id = comments.post_id
|
||||
```
|
||||
|
||||
Индекс по `posts.id` бесполезен. Индекс по `comments.post_id` обязателен. Если вы создадите индекс, оптимизатор выберет Nested Loop, и все будет работать быстро.
|
||||
|
||||
|
||||
|
||||
## Почему JOIN работает медленно?
|
||||
- Индекс для полей по которым джойним добавлен?
|
||||
## Заметки
|
||||
- B MySQL используется метод nested loops, но с оптимизациями.
|
||||
- У вас оптимизатор из каких-то соображений выбирает Nested Loop, а вам кажется, что одна таблица очень маленькая, другая – очень большая и Hash Join там был бы очень уместен, потому что маленькую таблицу можно быстро прохэшировать и быстро с ней работать. Посмотрите, сколько у вас work mem'а. т.е. сколько памяти может занять один worker Postgres’а. Если эта таблица хэшируется в, например, 100 Мб, а у вас work mem'а выдано только 30 Мб, то worker будет работать медленно. Если вы добавите work mem'а и хэширование начнет вмещаться в память, оптимизатор выберет правильный Hash Join и будет быстро и хорошо.
|
@ -41,3 +41,5 @@ Memcached не является надежным хранилищем – воз
|
||||
Для распределения нагрузки и достижения отказоустойчивости вместо одного сервера memcached используется кластер из таких серверов. Сервера, входящие в кластер, могут быть сконфигурированы с различным объемом памяти, при этом общий объем кэша будет равен сумме объемов кэшей всех memcached, входящих в кластер. Процесс memcached может быть запущен на сервере, где слабо используется процессор и не загружена до предела сеть (например, на файловом сервере). При высокой нагрузке на процессор memcached может не успевать достаточно быстро отвечать на запросы, что приводит к деградации сервиса.
|
||||
|
||||
При работе с кластером ключи распределяются по серверам, то есть каждый сервер обрабатывает часть общего массива ключей проекта. Отказоустойчивость следует из того факта, что в случае отказа одного из серверов ключи будут перераспределены по оставшимся серверам кластера. При этом, конечно же, содержимое отказавшего сервера будет потеряно (см. раздел «Потеря ключей»). Вслучае необходимости важные ключи можно хранить не на одном сервере, а дублировать на нескольких, так можно минимизировать последствия падения сервера за счет избыточности хранения.
|
||||
## Дополнительные материалы
|
||||
- [Web, кэширование и memcached](https://highload.guide/blog/web-caching-memcached.html)
|
||||
|
@ -7,12 +7,18 @@ date:
|
||||
- - 2024-02-26
|
||||
zero-link:
|
||||
- "[[00 HighLoad]]"
|
||||
parents: []
|
||||
parents:
|
||||
linked:
|
||||
- "[[High Availability]]"
|
||||
---
|
||||
Это метод повышения [High Availability](High%20Availability.md). Обеспечивается техническими и организационными средствами.
|
||||
|
||||
Техническое средство - избыточность:
|
||||
- сервисов
|
||||
- active-passive. Это когда запасной сервис заранее поднят, но не используется.
|
||||
- параллельные кластеры.
|
||||
- данных
|
||||
- [Репликация](source/курсы/otus/Архитектор%20высоких%20нагрузок%202019/Репликация.md)
|
||||
|
||||
Организационные средства:
|
||||
- Дежурства разработчиков и DevOps
|
@ -24,11 +24,12 @@ linked:
|
||||
- Усложненное технического обслуживание. Индексы пухнут и переодически их нужно пересоздавать
|
||||
|
||||
**Когда индексы не нужны?**
|
||||
- Малая [Селективность колонки](Селективность%20колонки.md)
|
||||
- Накладные расходы на поддержание индекса больше пользы
|
||||
- Малая [Селективность колонки](Селективность%20колонки.md).
|
||||
- Большие накладные расходы на поддержание индекса.
|
||||
- Когда индекс не используется вовсе.
|
||||
|
||||
**Когда индексы не работают?**
|
||||
- В условии используется вычисляемое выражение: `WHERE counter + 1 = 46`
|
||||
- Если будет отобрано слишком много записей.
|
||||
- Из агрегирующих функций только `min()` и `max()` получат ускорение.
|
||||
- Индексы хорошо работают с логическим И, и плохо работают с логическим ИЛИ.
|
||||
@ -78,7 +79,7 @@ linked:
|
||||
- Собрать статистику нагрузки на БД от запросов.
|
||||
- Представление [pg_stats](Таблица%20статистик%20pg_stats.md).
|
||||
- Инструменты для сбора статистики:
|
||||
- pg_stat_statements - отличный инструмент
|
||||
- [pg_stat_statements](pg_stat_statements.md) - отличный инструмент
|
||||
- pgBadger - использовать с осторожностью. Собирает статистику из логов postgres. Но в логи попадают не все запросы.
|
||||
- Иметь примеры запросов с параметрами.
|
||||
- Для понимания входящих параметров запроса.
|
||||
@ -89,7 +90,7 @@ linked:
|
||||
|
||||
При создании индекса важно учитывать [селективность колонки](Селективность%20колонки.md) (разнообразие значений), чем она выше, тем лучше индекс будет выполнять свою задачу.
|
||||
|
||||
![](Составные%20индексы%20в%20PostgreSQL.md#^630c7e)
|
||||
![](Составные%20индексы%20в%20БД.md#^630c7e)
|
||||
|
||||
- [PostgreSQL: Documentation: 16: CREATE INDEX](https://www.postgresql.org/docs/current/sql-createindex.html)
|
||||
|
||||
|
33
_inbox/Индексы в MySQL.md
Normal file
33
_inbox/Индексы в MySQL.md
Normal file
@ -0,0 +1,33 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- зрелость/🌱
|
||||
date:
|
||||
- - 2024-06-16
|
||||
zero-link:
|
||||
- "[[00 MySQL]]"
|
||||
parents:
|
||||
linked:
|
||||
---
|
||||
![Архитектура](Архитектура%20MySQL.md#^42f122)
|
||||
|
||||
Индексы реализуются на уровне движка хранилища, они не стандартизованы. Каждый движок может предоставлять свою реализацию одного и того же индекса. Например, B-Tree индекс в MyISAM хранит указатель на сами данные, а в InnoDB он хранит указатель на первичный ключ; в MyISAM происходит сжатие префиксных индексов, а в InnoDB этого не происходит, но зато там есть кэширование и данных, и индексов.
|
||||
|
||||
> [!WARNING] Дублирование индексов
|
||||
> MySQL никак не управляет дублированием индексов. Например, если создать таблицу с PK, а потом создать на PK индекс и UNIQUE(PK), то мы получим не один, а 3 одинаковых индекса.
|
||||
|
||||
Если у нас есть index(A) и index(A,B), то index(A) будет лишним, потому что в случае index(A,B) часть А может использоваться в нем. (если оба [B-tree](B-tree.md))
|
||||
|
||||
Используются [покрывающие индексы](Покрывающий%20индекс.md)
|
||||
|
||||
[Extended keys MySQL](Extended%20keys%20MySQL.md)
|
||||
|
||||
**Когда индексы не работают?**
|
||||
- Часть выражения: id + 1 = 3.
|
||||
- Когда есть преобразование типов: key_str = 15
|
||||
- Несоответсвие кодировок
|
||||
- Не используется левая часть [составного индекса](Составные%20индексы%20в%20MySQL.md): index(a,b); where b = 5;
|
||||
- Поиск по суффиксу: '%x'
|
||||
- Сравнение с исходной таблицей: t.key = t.col
|
||||
|
||||
Например, A in (0,1) и А between 0 and 1 – это эквивалентные формы, это диапазон и там, и там, но в случае, когда это A in (0,1) – список, он понимает, что это не диапазон, а заменяет на множественное условие равенства. В этом случае он будет использовать индекс. Это еще один нюанс MySQL, т.е. нужно смотреть, как писать – либо списком, либо ставить <> . Он это различает.
|
@ -14,7 +14,7 @@ linked:
|
||||
|
||||
Ускорить сложные запросы может кэширование: мы помещаем результат вычислений в некоторое хранилище (например, [Memcached](Memcached.md) или [Redis](Redis.md)), которое обладает отличными характеристиками по времени доступа к информации. Теперь вместо обращений к медленным, сложным и тяжелым backend’ам нам достаточно выполнить запрос к быстрому кэшу.
|
||||
|
||||
Системы используемые для кэширования обычно не являются надежными, так что не следует хранить только там какие-то важные данные. Данные можно разделить на несколько категорий:
|
||||
==Системы используемые для кэширования обычно не являются надежными, так что не следует хранить только там какие-то важные данные.== Данные можно разделить на несколько категорий:
|
||||
- «**Можно потерять**». К этой категории относятся кэши выборок из базы данных. Потеря таких ключей не так страшна, потому что мы можем легко восстановить их значения, обратившись заново к backend’у. Однако частые потери кэшей приводят к излишним обращениям к БД.
|
||||
- «**Не хотелось бы потерять**». Здесь можно упомянуть счетчики посетителей сайта, просмотров ресурсов и т.п. Хоть и восстановить эти значения иногда напрямую невозможно, но значения этих ключей имеют ограниченный по времени смысл: через несколько минут их значение уже неактуально, и будет рассчитано заново.
|
||||
- «**Совсем не должны терять**». Кэш удобен для хранения сессий пользователей. Однако содержимое сессий не хотелось бы терять никогда – иначе пользователей на сайте будет «разлогинивать». Как попытаться избежать? Можно кластеризовать систему кэширования, так вероятность потери снижается.
|
||||
|
344
_inbox/Настройка репликации в PostgreSQL.md
Normal file
344
_inbox/Настройка репликации в PostgreSQL.md
Normal file
@ -0,0 +1,344 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- зрелость/🌱
|
||||
date:
|
||||
- - 2024-06-17
|
||||
zero-link:
|
||||
- "[[00 PostgreSQL]]"
|
||||
parents:
|
||||
- "[[Репликация в PostgreSQL]]"
|
||||
linked:
|
||||
---
|
||||
## Физическая репликация
|
||||
1. Создаем сеть, запоминаем адрес
|
||||
```shell
|
||||
docker network create pgnet
|
||||
docker network inspect pgnet | grep Subnet # Запомнить маску сети
|
||||
```
|
||||
|
||||
2. Поднимаем мастер
|
||||
```shell
|
||||
docker run -dit -v "$PWD/volumes/pgmaster/:/var/lib/postgresql/data" -e POSTGRES_PASSWORD=pass -p "5432:5432" --restart=unless-stopped --network=pgnet --name=pgmaster postgres
|
||||
```
|
||||
|
||||
3. Меняем postgresql.conf на мастере
|
||||
```conf
|
||||
ssl = off
|
||||
wal_level = replica
|
||||
max_wal_senders = 4 # expected slave num
|
||||
```
|
||||
|
||||
4. Подключаемся к мастеру и создаем пользователя для репликации
|
||||
```shell
|
||||
docker exec -it pgmaster su - postgres -c psql
|
||||
create role replicator with login replication password 'pass';
|
||||
exit
|
||||
```
|
||||
|
||||
5. Добавляем запись в `pgmaster/pg_hba.conf` с `subnet` с первого шага
|
||||
```
|
||||
host replication replicator __SUBNET__ md5
|
||||
```
|
||||
|
||||
6. Перезапустим мастер
|
||||
```shell
|
||||
docker restart pgmaster
|
||||
```
|
||||
|
||||
7. Сделаем бэкап для реплик
|
||||
```shell
|
||||
docker exec -it pgmaster bash
|
||||
mkdir /pgslave
|
||||
pg_basebackup -h pgmaster -D /pgslave -U replicator -v -P --wal-method=stream
|
||||
exit
|
||||
```
|
||||
|
||||
8. Копируем директорию себе
|
||||
```shell
|
||||
docker cp pgmaster:/pgslave volumes/pgslave/
|
||||
```
|
||||
|
||||
9. Создадим файл, чтобы реплика узнала, что она реплика
|
||||
```shell
|
||||
touch volumes/pgslave/standby.signal
|
||||
```
|
||||
|
||||
10. Меняем `postgresql.conf` на реплике `pgslave`
|
||||
```conf
|
||||
primary_conninfo = 'host=pgmaster port=5432 user=replicator password=pass application_name=pgslave'
|
||||
```
|
||||
|
||||
11. Запускаем реплику `pgslave`
|
||||
```shell
|
||||
docker run -dit -v "$PWD/volumes/pgslave/:/var/lib/postgresql/data" -e POSTGRES_PASSWORD=pass -p "15432:5432" --network=pgnet --restart=unless-stopped --name=pgslave postgres
|
||||
```
|
||||
|
||||
12. Запустим вторую реплику `pgasyncslave`
|
||||
- скопируем бэкап
|
||||
```shell
|
||||
docker cp pgmaster:/pgslave volumes/pgasyncslave/
|
||||
```
|
||||
|
||||
- изменим настройки `pgasyncslave/postgresql.conf`
|
||||
```conf
|
||||
primary_conninfo = 'host=pgmaster port=5432 user=replicator password=pass application_name=pgasyncslave'
|
||||
```
|
||||
|
||||
- дадим знать что это реплика
|
||||
```shell
|
||||
touch volumes/pgasyncslave/standby.signal
|
||||
```
|
||||
|
||||
- запустим реплику `pgasyncslave`
|
||||
```shell
|
||||
docker run -dit -v "$PWD/volumes/pgasyncslave/:/var/lib/postgresql/data" -e POSTGRES_PASSWORD=pass -p "25432:5432" --network=pgnet --restart=unless-stopped --name=pgasyncslave postgres
|
||||
```
|
||||
|
||||
14. Убеждаемся что обе реплики работают в асинхронном режиме на `pgmaster`
|
||||
```shell
|
||||
docker exec -it pgmaster su - postgres -c psql
|
||||
select application_name, sync_state from pg_stat_replication;
|
||||
exit;
|
||||
```
|
||||
|
||||
15. Включаем синхронную репликацию на `pgmaster`
|
||||
- меняем файл `pgmaster/postgresql.conf`
|
||||
```conf
|
||||
synchronous_commit = on
|
||||
synchronous_standby_names = 'FIRST 1 (pgslave, pgasyncslave)'
|
||||
```
|
||||
|
||||
- перечитываем конфиг
|
||||
```shell
|
||||
docker exec -it pgmaster su - postgres -c psql
|
||||
select pg_reload_conf();
|
||||
exit;
|
||||
```
|
||||
|
||||
16. Убеждаемся, что реплика стала синхронной
|
||||
```shell
|
||||
docker exec -it pgmaster su - postgres -c psql
|
||||
select application_name, sync_state from pg_stat_replication;
|
||||
exit;
|
||||
```
|
||||
|
||||
17. Создадим тестовую таблицу на `pgmaster` и проверим репликацию
|
||||
```shell
|
||||
docker exec -it pgmaster su - postgres -c psql
|
||||
create table test(id bigint primary key not null);
|
||||
insert into test(id) values(1);
|
||||
select * from test;
|
||||
exit;
|
||||
```
|
||||
|
||||
18. Проверим наличие данных на `pgslave`
|
||||
```shell
|
||||
docker exec -it pgslave su - postgres -c psql
|
||||
select * from test;
|
||||
exit;
|
||||
```
|
||||
|
||||
19. Проверим наличие данных на `pgasyncslave`
|
||||
```shell
|
||||
docker exec -it pgasyncslave su - postgres -c psql
|
||||
select * from test;
|
||||
exit;
|
||||
```
|
||||
20. Попробуем сделать `insert` на `pgslave`
|
||||
```shell
|
||||
docker exec -it pgslave su - postgres -c psql
|
||||
insert into test(id) values(2);
|
||||
exit;
|
||||
```
|
||||
21. Укладываем репилку `pgasyncslave` и проверяем работу `pgmaster` и `pgslave`
|
||||
```shell
|
||||
docker stop pgasyncslave
|
||||
docker exec -it pgmaster su - postgres -c psql
|
||||
select application_name, sync_state from pg_stat_replication;
|
||||
insert into test(id) values(2);
|
||||
select * from test;
|
||||
exit;
|
||||
docker exec -it pgslave su - postgres -c psql
|
||||
select * from test;
|
||||
exit;
|
||||
```
|
||||
22. Укладываем репилку `pgslave` и проверяем работу `pgmaster`, а потом возвращаем реплику `pgslave`
|
||||
- terminal 1
|
||||
```shell
|
||||
docker stop pgslave
|
||||
docker exec -it pgmaster su - postgres -c psql
|
||||
select application_name, sync_state from pg_stat_replication;
|
||||
insert into test(id) values(3);
|
||||
exit;
|
||||
```
|
||||
- terminal 2
|
||||
```shell
|
||||
docker start pgslave
|
||||
```
|
||||
23. Возвращаем вторую реплику `pgasyncslave`
|
||||
```shell
|
||||
docker start pgasyncslave
|
||||
```
|
||||
24. Убиваем мастер `pgmaster`
|
||||
```shell
|
||||
docker stop pgmaster
|
||||
```
|
||||
25. Запромоутим реплику `pgslave`
|
||||
```shell
|
||||
docker exec -it pgslave su - postgres -c psql
|
||||
select pg_promote();
|
||||
exit;
|
||||
```
|
||||
26. Пробуем записать в новый мастер `pgslave`
|
||||
```shell
|
||||
docker exec -it pgslave su - postgres -c psql
|
||||
insert into test(id) values(4);
|
||||
exit;
|
||||
```
|
||||
|
||||
27. Настраиваем репликацию на `pgslave` (`pgslave/postgresql.conf`)
|
||||
- изменяем конфиг
|
||||
```conf
|
||||
synchronous_commit = on
|
||||
synchronous_standby_names = 'ANY 1 (pgmaster, pgasyncslave)'
|
||||
```
|
||||
- перечитываем конфиг
|
||||
```shell
|
||||
docker exec -it pgslave su - postgres -c psql
|
||||
select pg_reload_conf();
|
||||
exit;
|
||||
```
|
||||
|
||||
28. Подключим вторую реплику `pgasyncslave` к новому мастеру `pgslave`
|
||||
- изменяем конфиг `pgasyncslave/postgresql.conf`
|
||||
```conf
|
||||
primary_conninfo = 'host=pgslave port=5432 user=replicator password=pass application_name=pgasyncslave'
|
||||
```
|
||||
- перечитываем конфиг
|
||||
```shell
|
||||
docker exec -it pgasyncslave su - postgres -c psql
|
||||
select pg_reload_conf();
|
||||
exit;
|
||||
```
|
||||
29. Проверяем что к новому мастеру `pgslave` подключена реплика и она работает
|
||||
```shell
|
||||
docker exec -it pgslave su - postgres -c psql
|
||||
select application_name, sync_state from pg_stat_replication;
|
||||
insert into test(id) values (5)
|
||||
select * from test;
|
||||
exit;
|
||||
docker exec -it pgasyncslave su - postgres -c psql
|
||||
select * from test;
|
||||
exit;
|
||||
```
|
||||
30. Восстановим старый мастер `pgmaster` как реплику
|
||||
1. Помечаем как реплику
|
||||
```shell
|
||||
touch volumes/pgmaster/standby.signal
|
||||
```
|
||||
2. Изменяем конфиг `pgmaster/postgresql.conf`
|
||||
```conf
|
||||
primary_conninfo = 'host=pgslave port=5432 user=replicator password=pass application_name=pgmaster'
|
||||
```
|
||||
3. Запустим `pgmaster`
|
||||
```shell
|
||||
docker start pgmaster
|
||||
```
|
||||
4. Убедимся что `pgmaster` подключился как реплика к `pgslave`
|
||||
```shell
|
||||
docker exec -it pgslave su - postgres -c psql
|
||||
select application_name, sync_state from pg_stat_replication;
|
||||
exit;
|
||||
```
|
||||
|
||||
## Логическая репликация
|
||||
1. Меняем `wal_level` для текущего мастера `pgslave`
|
||||
1. Изменяем настройки `pgslave/postgresql.conf`
|
||||
```conf
|
||||
wal_level = logical
|
||||
```
|
||||
2. Перезапускаем `pgslave`
|
||||
```shell
|
||||
docker restart pgslave
|
||||
```
|
||||
2. Создадим публикацию в `pgslave`
|
||||
```shell
|
||||
docker exec -it pgslave su - postgres -c psql
|
||||
GRANT CONNECT ON DATABASE postgres TO replicator;
|
||||
GRANT SELECT ON ALL TABLES IN SCHEMA public TO replicator;
|
||||
create publication pg_pub for table test;
|
||||
exit;
|
||||
```
|
||||
3. Создадим новый сервер `pgstandalone` для логической репликации
|
||||
```shell
|
||||
docker run -dit -v "$PWD/volumes/pgstandalone/:/var/lib/postgresql/data" -e POSTGRES_PASSWORD=pass -p "35432:5432" --restart=unless-stopped --network=pgnet --name=pgstandalone postgres
|
||||
```
|
||||
4. Копируем файлы c `pgslave` в `pgstandalone` и восстанавливаем
|
||||
```shell
|
||||
docker exec -it pgslave su - postgres
|
||||
pg_dumpall -U postgres -r -h pgslave -f /var/lib/postgresql/roles.dmp
|
||||
pg_dump -U postgres -Fc -h pgslave -f /var/lib/postgresql/schema.dmp -s postgres
|
||||
exit;
|
||||
|
||||
docker cp pgslave:/var/lib/postgresql/roles.dmp .
|
||||
docker cp roles.dmp pgstandalone:/var/lib/postgresql/roles.dmp
|
||||
docker cp pgslave:/var/lib/postgresql/schema.dmp .
|
||||
docker cp schema.dmp pgstandalone:/var/lib/postgresql/schema.dmp
|
||||
|
||||
docker exec -it pgstandalone su - postgres
|
||||
psql -f roles.dmp
|
||||
pg_restore -d postgres -C schema.dmp
|
||||
exit
|
||||
```
|
||||
|
||||
5. Создаем подписку на `pgstandalone`
|
||||
```shell
|
||||
docker exec -it pgstandalone su - postgres -c psql
|
||||
CREATE SUBSCRIPTION pg_sub CONNECTION 'host=pgslave port=5432 user=replicator password=pass dbname=postgres' PUBLICATION pg_pub;
|
||||
exit;
|
||||
```
|
||||
6. Убеждаемся что репликация запущена
|
||||
```shell
|
||||
docker exec -it pgstandalone su - postgres -c psql
|
||||
select * from test;
|
||||
exit;
|
||||
```
|
||||
7. Сделаем конфликт в данных
|
||||
1. Вставляем данные в подписчике `pgstandalone`
|
||||
```shell
|
||||
docker exec -it pgstandalone su - postgres -c psql
|
||||
insert into test values(9);
|
||||
exit;
|
||||
```
|
||||
2. Вставляем данные в паблишере `pgslave`
|
||||
```shell
|
||||
docker exec -it pgslave su - postgres -c psql
|
||||
insert into test values(9);
|
||||
insert into test values(10);
|
||||
exit;
|
||||
```
|
||||
3. Убеждаемся что записи с id 10 не появилось на `pgstandalone`
|
||||
```shell
|
||||
docker exec -it pgstandalone su - postgres -c psql
|
||||
select * from test;
|
||||
exit;
|
||||
```
|
||||
4. Посмотрим в логи `pgstandalone` и убедимся что у нас произошел разрыв репликации
|
||||
```shell
|
||||
docker logs pgstandalone
|
||||
```
|
||||
```
|
||||
2023-03-27 16:15:02.753 UTC [258] ERROR: duplicate key value violates unique constraint "test_pkey"
|
||||
2023-03-27 16:15:02.753 UTC [258] DETAIL: Key (id)=(9) already exists.
|
||||
2023-03-28 18:30:42.893 UTC [108] CONTEXT: processing remote data for replication origin "pg_16395" during message type "INSERT" for replication target relation "public.test" in transaction 739, finished at 0/3026450
|
||||
```
|
||||
|
||||
8. Исправляем конфликт
|
||||
```shell
|
||||
docker exec -it pgstandalone su - postgres -c psql
|
||||
SELECT pg_replication_origin_advance('pg_16395', '0/3026451'::pg_lsn); # message from log + 1
|
||||
ALTER SUBSCRIPTION pg_sub ENABLE;
|
||||
select * from test;
|
||||
exit;
|
||||
```
|
53
_inbox/Оптимизация SQL запросов.md
Normal file
53
_inbox/Оптимизация SQL запросов.md
Normal file
@ -0,0 +1,53 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- зрелость/🌱
|
||||
date:
|
||||
- - 2024-06-17
|
||||
zero-link:
|
||||
- "[[00 Базы Данных]]"
|
||||
parents:
|
||||
- "[[00 SQL]]"
|
||||
linked:
|
||||
---
|
||||
Что такое плохой или медленный запрос
|
||||
- Запрос по времени работает дольше остальных
|
||||
- Запрос, который потребляет больше ресурсов, чем остальные запросы
|
||||
- Быстро выполняемый запрос может быть также плохим, если выполняется часто и в сумме за N времени потребляет много ресурсов.
|
||||
|
||||
**Алгоритм оптимизации запросов:**
|
||||
- Проверить настройки. Возможно проблемы не связаны с запросами?
|
||||
- Слабое железо у сервера БД
|
||||
- Проблемы сети
|
||||
- Неправильные настройки БД
|
||||
- [PostgreSQL](00%20PostgreSQL.md)
|
||||
- Много конекшенов, но ее используется [PgBouncer](PgBouncer.md).
|
||||
- Выключен или не настроен autovacuum
|
||||
- Отобрать запросы для оптимизации
|
||||
- ==Анализом необходимо заниматься только на продуктовой БД.==
|
||||
- Все подряд оптимизировать бесполезно. Нужно отобрать самые проблемные и начать с них.
|
||||
- [PostgreSQL](00%20PostgreSQL.md)
|
||||
- Использовать [GitHub - Полезные утилиты для тюнинга PostgreSQL](https://github.com/dataegret/pg-utils) - global_reports
|
||||
- Использовать [[pg_stat_statements]]
|
||||
- Оптимизировать запросы
|
||||
- Использовать [Explain в PostgreSQL](Explain%20в%20PostgreSQL.md) и [Explain в MySQL](Explain%20в%20MySQL.md) для анализа запросов
|
||||
- Повторить с новыми запросами из топа.
|
||||
|
||||
**Где могут быть проблемы?**
|
||||
- Передача запроса от клиента (сервиса). [Пример при использовании IN](IN%20SQL.md#Проблемы%20производительности%20IN)
|
||||
- Сложный запрос, который долго парсится. Можно посмотреть в explain.
|
||||
- БД долго вычисляет план запроса и проводит оптимизации. Например, при использовании join.
|
||||
- Исполнение и возврат результатов. Если вы возвращаете несколько гигабайт, это не будет быстро.
|
||||
|
||||
**Как улучшить?**
|
||||
- Переписать запрос
|
||||
- Использовать [Индексы в MySQL](Индексы%20в%20MySQL.md) / [Индекс в PostgreSQL](Индекс%20в%20PostgreSQL.md)
|
||||
|
||||
**Невозможно улучшить**
|
||||
- count(\*). Можно использовать приближенное значение из таблицы статистики.
|
||||
- join на 300 таблиц
|
||||
- Запрос возвращает клиенту 1 000 000 000 строк
|
||||
|
||||
![Почему JOIN работает медленно?](JOIN%20SQL.md#Почему%20JOIN%20работает%20медленно?)
|
||||
|
||||
![Проблемы производительности IN](IN%20SQL.md#Проблемы%20производительности%20IN)
|
@ -7,8 +7,7 @@ date:
|
||||
- - 2024-06-09
|
||||
zero-link:
|
||||
- "[[00 Базы Данных]]"
|
||||
parents:
|
||||
- "[[Индекс в PostgreSQL]]"
|
||||
parents: []
|
||||
linked:
|
||||
---
|
||||
Покрывающий индекс - это индекс, который включает в себя все колонки, необходимые для выполнения определенного запроса, без необходимости обращения к основной таблице данных.
|
||||
|
@ -32,6 +32,10 @@ linked:
|
||||
- Устойчивость к проблемам сети
|
||||
- Hot-standby реплика (VIP). Второй мастер всегда на готове, если упадет основной, но не используется.
|
||||
- Offline клиенты. При плохом интернет соединении для асинхронного объединения данных. Пример БД CouchDB.
|
||||
|
||||
Варианты реализаций:
|
||||
- Amazon Aurora
|
||||
- Google Spanner
|
||||
## Решение конфликтов
|
||||
- Избегайте конфликтов
|
||||
- Last write wins. Выигрывает последняя запись. Но обычно сложно определить кто был первым.
|
||||
|
@ -19,3 +19,8 @@ linked:
|
||||
- Этот способ никогда не даст 99,9999 [High Availability](High%20Availability.md).
|
||||
|
||||
![](Pasted%20image%2020240206194227.png)
|
||||
|
||||
Управление master-slave:
|
||||
- MHA (MySQL Master HA)
|
||||
- MySQL Failover (Oracle)
|
||||
- Orchestrator
|
@ -20,6 +20,7 @@ link: https://highload.guide/blog/asynchronous-replication.html
|
||||
- Обязательно убедиться, что работают GUID идентификация транзакций.
|
||||
***
|
||||
|
||||
|
||||
**Репликация сильно зависит от версии MySql**
|
||||
- Всегда логическая репликация, модель master-slave, pull распространение
|
||||
- 4.1 = асинхронная, SBR, logposs
|
||||
@ -28,6 +29,10 @@ link: https://highload.guide/blog/asynchronous-replication.html
|
||||
- 5.7 = + mtslave, +master-master (plugin), +default-RBR (image=full?!), groupcommit
|
||||
|
||||
## Схема работы репликации
|
||||
![Архитектура MySQL](Архитектура%20MySQL.md#^42f122)
|
||||
|
||||
Такая плагинная архитектура позволяет устанавливать новый движок, но мгновенно возникает неоптимальность. В принципе, транзакционные write-ahead log'и (WAL), которые физический слой хранения все равно пишет, было бы хорошо использовать для репликации, и если система знает о том, что есть некий физический уровень, или достаточно хорошо сопряжена с этим физическим уровнем, то можно было бы отдельный лог на логическом уровне не писать, а использовать тот же самый WAL. Но у MySQL это невозможно концептуально, либо, если поменять интерфейс в PSE так, чтобы стало возможно концептуально, то будет очень много работы.
|
||||
|
||||
При включении репликации на логическом уровне MySQL мастер начинает вести binary log – файл, в который сыплются все подряд изменения.
|
||||
|
||||
У слэйва чуть больше работы. Помимо того, чтобы вести один дополнительный лог(relay log) и по запросу его рассылать, еще есть поток, который ходит к удаленному мастеру, возможно, даже не к одному, и качает оттуда binary log'и. Еще отдельный поток пытается исполнять эти локальные логи.
|
||||
|
@ -47,6 +47,7 @@ Sync/Semi-symc:
|
||||
- Нужно идентифицировать запись для update/delete (по первичному ключу/по уникальному ненуллабельному индексу/по всем столбцам).
|
||||
- В случае возникновения конфликта требуется вручную исправить данные.
|
||||
## Дополнительные материалы
|
||||
- [Настройка репликации в PostgreSQL](Настройка%20репликации%20в%20PostgreSQL.md)
|
||||
- [BDR User Guide - PostgreSQL wiki](https://wiki.postgresql.org/wiki/Logical_Log_Streaming_Replication)
|
||||
- [Site Unreachable](http://www.postgresql.org/docs/9.4/static/logicaldecoding.html) Аналог [libslave](libslave.md) в MySQL
|
||||
- [Отладка и устранение проблем в PostgreSQL Streaming Replication / Хабр](https://m.habr.com/ru/company/oleg-bunin/blog/414111/)
|
||||
|
27
_inbox/Составные индексы в MySQL.md
Normal file
27
_inbox/Составные индексы в MySQL.md
Normal file
@ -0,0 +1,27 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- зрелость/🌱
|
||||
date:
|
||||
- - 2024-06-16
|
||||
zero-link:
|
||||
- "[[00 MySQL]]"
|
||||
parents:
|
||||
- "[[Индексы в MySQL]]"
|
||||
linked:
|
||||
---
|
||||
![Составные индексы в БД](Составные%20индексы%20в%20БД.md)
|
||||
|
||||
В MySQL для составного индекса не допускаются пропуски колонок в запросе. Также индекс будет использован до первого неравенства в запросе.
|
||||
|
||||
Если у нас в запросе есть поиск по списку (IN), то индекс будет использоваться для списка и операций равенств, но не будет использоваться для сортировок. Лучше в таком случае использовать UNION.
|
||||
|
||||
Например, если у нас есть INDEX(A,B,C), то
|
||||
- WHERE A = 10 AND B > 405. Индекс будет использоваться только для первой части
|
||||
- WHERE A = 10 AND B = 9 AND C < 50. Индекс будет использоваться полностью.
|
||||
- WHRE A = 10 AND B = 7 ORDER BY 7. Индекс будет использоваться полностью.
|
||||
- WHERE B = 3; ==индекс использоваться не будет==
|
||||
- WHERE A=10 AND B>4 AND C>17; Индекс будет использоваться только для первых двух частей
|
||||
- WHERE A=10 ORDER BY C; Индекс будет использоваться только на первую часть
|
||||
- WHERE A=10 ORDER BY B, C; Индекс будет использован целиком
|
||||
- WHERE A=10 ORDER BY B, C DESC; Индекс будет использован только на первую часть. Для сортировки индекс используется только в одном направлении.
|
@ -10,13 +10,9 @@ parents:
|
||||
- "[[Индекс в PostgreSQL]]"
|
||||
linked:
|
||||
---
|
||||
Составным называется индекс, который включает в себя несколько полей.
|
||||
![Составные индексы в БД](Составные%20индексы%20в%20БД.md)
|
||||
|
||||
==В составных индексах важен порядок столбцов.== Порядок полей в индексе должен учитывать [селективность каждой колонки](Селективность%20колонки.md), то есть насколько уникальными являются значения в столбце. В идеале более селективные поля должны идти первыми в индексе, чтобы максимизировать эффективность индекса. ^630c7e
|
||||
|
||||
При поиске по составному индексу, сначала сравн иттвается первый элемент указанный в индексе, потом второй и так далее. Поэтому запросы, которые не следуют этому порядку колонок являются не оптимальными.
|
||||
|
||||
Частичное использование индекса. Используется до первого неравенства.
|
||||
- a > 0 and b = 4. Индекс будет использоваться для всех колонок
|
||||
- a = 0 and b > 3 and c = 3. Индекс будет использоваться для первых двух колонок,
|
||||
- a = 0 and b > 3 and c > 3. Индекс будет использоваться только для первой колонки.
|
||||
Частичное использование индекса. Используется до первого неравенства включительно.
|
||||
- a > 0 and b = 4. Индекс будет использоваться для всех колонок. Не смотря на то, что первая часть это неравенство.
|
||||
- a = 0 and b > 3 and c = 3. Индекс будет использоваться для первых двух колонок. После нера
|
||||
- a = 0 and b > 3 and c > 3. Индекс будет использоваться для первой и второй колонки.
|
@ -10,4 +10,11 @@ parents:
|
||||
linked:
|
||||
---
|
||||
|
||||
- Большинство существительных и прилагательных, состоящих из 2 слогов имеют ударение на первый слог.
|
||||
- В глаголах из двух слогов чаще всего ударение падает на последний слог
|
||||
- В составных (более одного корня) существительных чаще всего ударение падает на первый корень (первый слог).
|
||||
- В составных глаголах и прилагательных ударной является вторая часть
|
||||
|
||||
![](Pasted%20image%2020240608091642.png)
|
||||
|
||||
Ударение падает на предпоследний слог ![](Pasted%20image%2020240615073511.png)
|
@ -8,7 +8,7 @@ date:
|
||||
zero-link:
|
||||
- "[[00 Базы Данных]]"
|
||||
parents:
|
||||
- "[[SQL]]"
|
||||
- "[[00 SQL]]"
|
||||
linked:
|
||||
---
|
||||
LIKE может выполняться с индексом, но только по префиксу. Например, LIKE 'a%' - хорошо, а LIKE '%c' - плохо.
|
@ -7,7 +7,13 @@ date:
|
||||
zero-link:
|
||||
- "[[00 Базы Данных]]"
|
||||
parents:
|
||||
- "[[SQL]]"
|
||||
- "[[00 SQL]]"
|
||||
linked:
|
||||
---
|
||||
При использовании разно-направленной сортировки (`ORDER BY a DESC, b ASC`) не используются индексы. Хотя MySQL 8+ поддерживает такие сортировки, но нужно создавать специальный разно-направленный индекс.
|
||||
|
||||
ORDER BY id LIMIT 10000, 10 – это плохо, т.к. сервер будет выбирать все 10 тыс. строк + еще 10, потом 1001-ю отбрасывать и только 10 выдавать. Такие вещи надо каким-то образом менять. Либо ID больше 10 000, LIMIT 10. Когда у нас offset большое число – с точки зрения того, что делает сервер, это плохо.
|
||||
|
||||
Нельзя использовать ORDER BY rand(), т.к. эта структура делает копию всех наших данных, загоняет во временную таблицу, добавляет туда еще один столбец, куда записывает результат функции rand и потом файловую сортировку всего этого огромного массива. Поэтому, если мы хотим выбрать случайную строку, ORDER BY rand() можно применять лишь на небольших объемах данных, на больших это сразу убьет всю производительность.
|
||||
|
||||
Группировка по умолчанию делает и сортировку, поэтому, если нам сортировка не нужна, то мы должны указать в явном виде – ORDER BY null.
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
aliases: []
|
||||
aliases:
|
||||
tags:
|
||||
- зрелость/🌱
|
||||
date:
|
||||
@ -7,9 +7,10 @@ date:
|
||||
zero-link:
|
||||
- "[[00 PostgreSQL]]"
|
||||
parents:
|
||||
- "[[Оптимизация SQL запросов]]"
|
||||
linked:
|
||||
---
|
||||
- [Explain](Explain.md)
|
||||
- [Explain в PostgreSQL](Explain%20в%20PostgreSQL.md)
|
||||
***
|
||||
PostgreSQL хранит статистику по выполнениям запросов в таблице `pg_stat_user_tables`. С её помощью можно оценить какие операции PostgreSQL выполняет чаще всего.
|
||||
|
||||
|
@ -9,5 +9,8 @@ zero-link:
|
||||
parents:
|
||||
linked:
|
||||
---
|
||||
- at - что-то находится у чего-то
|
||||
- on - что-то на чем-то
|
||||
- listen to - слушать кого-то
|
||||
- leave for - уезжать куда-то
|
||||
- waiting for - ждать кого-то
|
BIN
meta/files/Pasted image 20240615073511.png
Normal file
BIN
meta/files/Pasted image 20240615073511.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
BIN
meta/files/Pasted image 20240616113900.png
Normal file
BIN
meta/files/Pasted image 20240616113900.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 950 KiB |
BIN
meta/files/Pasted image 20240616114457.png
Normal file
BIN
meta/files/Pasted image 20240616114457.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 214 KiB |
BIN
meta/files/Pasted image 20240616122716.png
Normal file
BIN
meta/files/Pasted image 20240616122716.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 791 KiB |
BIN
meta/files/Pasted image 20240617132203.png
Normal file
BIN
meta/files/Pasted image 20240617132203.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 371 KiB |
BIN
meta/files/Pasted image 20240617132439.png
Normal file
BIN
meta/files/Pasted image 20240617132439.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 187 KiB |
Binary file not shown.
12
pg_stat_statements.md
Normal file
12
pg_stat_statements.md
Normal file
@ -0,0 +1,12 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- зрелость/🌱
|
||||
date:
|
||||
- - 2024-06-17
|
||||
zero-link:
|
||||
- "[[00 PostgreSQL]]"
|
||||
parents:
|
||||
- "[[Профилирование запросов в PostgreSQL]]"
|
||||
linked:
|
||||
---
|
@ -58,6 +58,7 @@
|
||||
- [Кронштейн для телевизора](Kromax20ATLANTIS-70.jpg), который позволяет его выдвинуть вперед перед кроватью
|
||||
- Коридор
|
||||
- Перед входом для обуви [резиновый коврик с сотами](orig-2.webp), чтобы грязь оставалась в нем
|
||||
- Автомтическая Чистилка обуви
|
||||
- Офис
|
||||
- Стул: herman miller
|
||||
- Массажное кресло
|
||||
|
@ -27,7 +27,7 @@ link: https://www.youtube.com/watch?v=ju9F8OvnL4E
|
||||
- Ориентироваться только на продуктовое окружение, так как тестовые окружения не соответствуют реальности.
|
||||
- Собрать статистику нагрузки на БД от запросов.
|
||||
- Инструменты для сбора статистики:
|
||||
- pg_stat_statements - отличный инструмент
|
||||
- [pg_stat_statements](pg_stat_statements.md) - отличный инструмент
|
||||
- pgBadger - использовать с осторожностью. Собирает статистику из логов postgres. Но в логи попадают не все запросы.
|
||||
- Иметь примеры запросов с параметрами.
|
||||
- Для понимания входящих параметров запроса.
|
||||
|
@ -33,3 +33,6 @@ zero-link:
|
||||
- [Кэширование данных в web приложениях. Использование memcached](https://highload.guide/blog/caching-data-in-web-applications.html)
|
||||
- [Использование memcached и Redis в высоконагруженных проектах](https://highload.guide/blog/using-memcached-and-redis.html)
|
||||
- [Как мы сделали ровную балансировку нагрузки на фронтенд-кластере](https://highload.guide/blog/load-balancing-frontend-cluster.html)
|
||||
- [NoSQL – коротко о главном](https://highload.guide/blog/NoSQL-quick-facts.html)
|
||||
- [Как выбрать In-memory NoSQL базу данных с умом. Тестируем производительность](https://highload.guide/blog/how-to-choose-In-memory-NoSQL-database.html)
|
||||
- [За счет чего Tarantool такой оптимальный](https://highload.guide/blog/optimal-tarantool.html)
|
@ -38,7 +38,7 @@ parents:
|
||||
- [Шардинг](Шардирование.md)
|
||||
- Виртуальные шарды
|
||||
- Центральный диспетчер
|
||||
- Репликация
|
||||
- [Репликация](_inbox/Репликация.md)
|
||||
- Партиционирование
|
||||
- Кластеризация
|
||||
- Денормализация
|
||||
|
@ -2,3 +2,8 @@
|
||||
tags:
|
||||
- type/zero-link
|
||||
---
|
||||
## Полезные команды
|
||||
Посмотреть общее свободно дисковое место в системе
|
||||
```shell
|
||||
df -h
|
||||
```
|
@ -9,12 +9,32 @@ zero-link:
|
||||
- [Репликация в MySQL](Репликация%20в%20MySQL.md)
|
||||
- [libslave](libslave.md)
|
||||
- [Бекап в MySQL](Бекап%20в%20MySQL.md)
|
||||
- [Индексы в MySQL](Индексы%20в%20MySQL.md)
|
||||
- [Журналы в MySQL](Журналы%20в%20MySQL.md)
|
||||
- [Explain в MySQL](Explain%20в%20MySQL.md)
|
||||
|
||||
## Архитектура MySQL
|
||||
![](Pasted%20image%2020240613195204.png)
|
||||
|
||||
Есть логический слой под названием MySQL, который занимается общими и изолированными от хранения данных операциями: кэширование, построение плана запроса и так далее. А есть конкретный физический слой, который отвечает за хранение данных. Он использует интерфейс подключения, то есть реализации хранилищ могут быть разными.
|
||||
|
||||
Логический слой, общий для всех движков:
|
||||
- В управлении подключением происходит авторизация. Каждый клиент работает в своем независимом потоке. Каждый поток может кэшироваться сервером.
|
||||
- Кэш запросов. Представлен одним общим потоком для всех клиентов. Может оказаться узким местом.
|
||||
- Парсер. Проверяет синтаксис запроса. Проверяет наличие прав доступа. Проверяет наличие ответов в кэше запросов.
|
||||
- Оптимизатор. Составляет план запроса. Из хранилища запрашивается статистика запросов.
|
||||
- Исполнитель. Обращается за данными в хранилище согласно плану запроса. Обновляет значения в кэше запросов.
|
||||
|
||||
|
||||
|
||||
Индексы реализуются на уровне движка хранилища, и каждый движок может предоставлять свою реализацию одного и того же индекса.
|
||||
|
||||
|
||||
![](Pasted%20image%2020240528082025.png)
|
||||
|
||||
Есть логический слой под названием MySQL, который занимается всяким общими и изолированными от хранения данных делами – сеть, оптимизатор, кэши и т.д. Конкретный физический слой, который отвечает за хранение данных, лежит на этаж ниже. Есть несколько встроенных, есть ставящиеся плагинами. Но даже встроенные MyISAM, InnoDB и т.д. живут на физическом слое. Плагинная архитектура позволяет устанавливать новый движок, но мгновенно возникает неоптимальность. В принципе, транзакционные write-ahead log'и (WAL), которые физический слой хранения все равно пишет, было бы хорошо использовать для репликации, и если система знает о том, что есть некий физический уровень, или достаточно хорошо сопряжена с этим физическим уровнем, то можно было бы отдельный лог на логическом уровне не писать, а использовать тот же самый WAL. Но у MySQL это невозможно концептуально, либо, если поменять интерфейс в PSE так, чтобы стало возможно концептуально, то будет очень много работы.
|
||||
|
||||
|
||||
|
||||
|
||||
- [Журналы в MySQL](Журналы%20в%20MySQL.md)
|
||||
## Идентификация транзакций
|
||||
|
@ -32,3 +32,6 @@ ps aux | grep nginx
|
||||
- [Кэширование на стороне клиента Nginx](Кэширование%20на%20стороне%20клиента%20Nginx.md)
|
||||
- [Балансировка запросов на Nginx](Балансировка%20запросов%20на%20Nginx.md)
|
||||
- [GZIP сжатие в Nginx](GZIP%20сжатие%20в%20Nginx.md)
|
||||
|
||||
## Дополнительные материалы
|
||||
- [Масштабируемая конфигурация nginx](https://highload.guide/blog/scalable-configuration-nginx.html)
|
@ -14,6 +14,9 @@ parents:
|
||||
- [Репликация в PostgreSQL](Репликация%20в%20PostgreSQL.md)
|
||||
- [Бэкап в PostgreSQL](Бэкап%20в%20PostgreSQL.md)
|
||||
- [Профилирование запросов в PostgreSQL](Профилирование%20запросов%20в%20PostgreSQL.md)
|
||||
- [Explain](Explain.md)
|
||||
- [Explain в PostgreSQL](Explain%20в%20PostgreSQL.md)
|
||||
|
||||
- PostgreSQL пишет на диск в два места – в хранилище данных и в журнал.
|
||||
|
||||
## Дополнительные материалы
|
||||
- [GitHub - Полезные утилиты для тюнинга PostgreSQL](https://github.com/dataegret/pg-utils)
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- зрелость/🌱
|
||||
- type/zero-link
|
||||
date:
|
||||
- - 2024-02-05
|
||||
zero-link:
|
||||
@ -11,6 +11,9 @@ linked:
|
||||
---
|
||||
- Таблица - это гомогенное множество кортежей
|
||||
|
||||
- [IN SQL](IN%20SQL.md)
|
||||
- [JOIN SQL](JOIN%20SQL.md)
|
||||
|
||||
## Производительность
|
||||
- Всегда добавлять индекс для Foreigner key
|
||||
- Подзапросы лучше, чем JOIN
|
49
Архитектура MySQL.md
Normal file
49
Архитектура MySQL.md
Normal file
@ -0,0 +1,49 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- зрелость/🌱
|
||||
date:
|
||||
- - 2024-06-16
|
||||
zero-link:
|
||||
- "[[00 MySQL]]"
|
||||
parents:
|
||||
linked:
|
||||
---
|
||||
В MysSQL есть логический слой, который занимается общими и изолированными от хранения данных операциями: кэширование, построение плана запроса и так далее. А есть конкретный физический слой, который отвечает за хранение данных. Он использует интерфейс подключения, то есть реализации хранилищ могут быть разными. ^42f122
|
||||
|
||||
Из-за этого возникают проблемы:
|
||||
- Репликация. Вынуждены писать несколько журналов, на логическом и физическом уровне
|
||||
- Индексы. Реализация одного и того же индекса может отличаться в разных хранилищах
|
||||
- Оптимизатор слабо связан с хранилищем, из-за этого он не может использовать какие-то особенности движка для улучшения производительности.
|
||||
|
||||
![](Pasted%20image%2020240613195204.png)
|
||||
|
||||
Клиенты, которые обращаются к серверу через функции соответствующего коннектора или C API по протоколу TCP/IP либо UNIX Socket.
|
||||
|
||||
Логический слой, общий для всех движков:
|
||||
- В управлении подключением происходит авторизация. Каждый клиент работает в своем независимом потоке. Каждый поток может кэшироваться сервером.
|
||||
- Кэш запросов. Представлен одним общим потоком для всех клиентов. Может оказаться узким местом.
|
||||
- Парсер проверяет синтаксис запроса, запрашивает у хранилищ наличие данных таблиц и полей, права доступа непосредственно к этим полям и проверяет наличие ответа в кэше запросов, после чего передает распарсенный запрос оптимизатору;
|
||||
- Оптимизатор запрашивает в интерфейсе хранилищ статистику по индексам, на основании которой он строит план запроса, который передает исполнителю;
|
||||
- Исполнитель. Обращается за данными в хранилище согласно плану запроса. Обновляет значения в кэше запросов.
|
||||
|
||||
![](Pasted%20image%2020240528082025.png)
|
||||
## Оптимизатор
|
||||
Выбирает самый производительный план.
|
||||
|
||||
План запроса, который делает оптимизатор, это не какой-то исполняемый код, а набор инструкций, который передается исполнителю. Это некое предположение о том, как запрос будет выполняться. В отличие от PostrgreSQL, мы не можем посмотреть как фактически был выполнен запрос. Данные от 2015 года, может что-то изменилось. ^432879
|
||||
|
||||
Какие пробоемы:
|
||||
- Из-за архитектуры MySQL
|
||||
- использует мало статистики по запросам.
|
||||
- не учитывает особенности хранилищ, нагрузку, буфферы соединений и кэши
|
||||
|
||||
Как влиять на оптимизатор?
|
||||
- Переписать запрос.
|
||||
- Использовать [индексы](Индексы%20в%20MySQL.md)
|
||||
- user/force/ignore index. Можем явно указать когда и какие индексы использовать
|
||||
- straight_join. Можем задать жесткий порядок join таблиц
|
||||
- @@optimizer_switch. Позволяет включать/отключать правила, которые использует оптимизатор.
|
||||
- optimizer_prune_level и optimizer_search_depth. Верхняя граница количества вариантов и времени выполнения, которые рассмотрит оптимизатор.
|
||||
|
||||
|
0
Без названия.md
Normal file
0
Без названия.md
Normal file
18
Составные индексы в БД.md
Normal file
18
Составные индексы в БД.md
Normal file
@ -0,0 +1,18 @@
|
||||
---
|
||||
aliases:
|
||||
tags:
|
||||
- зрелость/🌱
|
||||
date:
|
||||
- - 2024-06-16
|
||||
zero-link:
|
||||
- "[[00 Базы Данных]]"
|
||||
parents:
|
||||
linked:
|
||||
- "[[Составные индексы в PostgreSQL]]"
|
||||
- "[[Составные индексы в MySQL]]"
|
||||
---
|
||||
Составным называется индекс, который включает в себя несколько полей.
|
||||
|
||||
==В составных индексах важен порядок столбцов.== Порядок полей в индексе должен учитывать [селективность каждой колонки](Селективность%20колонки.md), то есть насколько уникальными являются значения в столбце. В идеале более селективные поля должны идти первыми в индексе, чтобы максимизировать эффективность индекса. ^630c7e
|
||||
|
||||
При поиске по составному индексу, сначала сравнивается первый элемент указанный в индексе, потом второй и так далее. Поэтому запросы, которые не следуют этому порядку колонок являются не оптимальными.
|
Loading…
Reference in New Issue
Block a user