Compare commits

...

2 Commits

Author SHA1 Message Date
bfae9ba8c7
Обновление
All checks were successful
continuous-integration/drone/push Build is passing
2024-11-05 00:33:50 +03:00
31f78d1f8b
Обновление 2024-11-05 00:33:37 +03:00
55 changed files with 284 additions and 66 deletions

27
dev/database/DB page.md Normal file
View File

@ -0,0 +1,27 @@
---
aliases:
- страница
- страницы
- страница БД
- Страница БД
- странице бд
tags:
- maturity/🌱
date: 2024-11-04
---
В базе данных страница — это базовая единица хранения данных, используемая для организации таблиц и индексов. Она представляет собой фиксированный блок данных (обычно 8 килобайт в PostgreSQL, но размер может варьироваться) и содержит строки таблицы или фрагменты индексов. Когда база данных выполняет запрос, она обращается к страницам, чтобы получить нужные строки, и может считывать их из диска или из кэша, где часто используемые страницы уже загружены в память.
База данных работает поверх операционной системы и поэтому использует [[../fundamental/Страница|страницы ОС]] для хранения своих страниц данных. Когда СУБД загружает страницу базы данных из диска, операционная система выделяет ей одну или несколько страниц оперативной памяти. В результате страницы базы данных хранятся в страницах памяти ОС.
***
## Мета информация
**Область**:: [[../../meta/zero/00 Базы Данных|00 Базы Данных]]
**Родитель**:: [[../fundamental/Страница|Страница]]
**Источник**::
**Создана**:: [[2024-11-04]]
**Автор**::
### Дополнительные материалы
-
### Дочерние заметки
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->

View File

@ -6,6 +6,8 @@ tags:
- maturity/🌱 - maturity/🌱
date: 2024-10-23 date: 2024-10-23
--- ---
![[../../../meta/files/images/Pasted image 20241104202857.png]]
**Особенности:** **Особенности:**
- Основан на работе [[../../fundamental/structure/B-tree|B-tree]] дерева. - Основан на работе [[../../fundamental/structure/B-tree|B-tree]] дерева.
- Подходит для операций сравнения (`<`, `>`, `BETWEEN`), равенства (`=`) и сортировки. - Подходит для операций сравнения (`<`, `>`, `BETWEEN`), равенства (`=`) и сортировки.
@ -27,7 +29,7 @@ CREATE INDEX idx_name ON table_name (column_name);
**Создана**:: [[2024-10-23]] **Создана**:: [[2024-10-23]]
**Автор**:: **Автор**::
### Дополнительные материалы ### Дополнительные материалы
- - [Владимир Ситников — B-tree индексы в базах данных на примере PostgreSQL - YouTube](https://www.youtube.com/watch?v=mnEU2_cwE_s)
### Дочерние заметки ### Дочерние заметки
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) --> <!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->

View File

@ -13,7 +13,7 @@ parents:
linked: linked:
- "[[Репликация в PostgreSQL]]" - "[[Репликация в PostgreSQL]]"
--- ---
В журнал попадают физические изменения, т.е. обновления страничек. Есть [[../../fundamental/Страница|страница]] в памяти, на ней лежат какие-то данные, мы с ней что-то сделали вот эту разницу мы записываем в журнал. В журнал попадают физические изменения, т.е. обновления страничек. Есть [[../DB page|страница]] в памяти, на ней лежат какие-то данные, мы с ней что-то сделали вот эту разницу мы записываем в журнал.
В WAL попадает всё: обновление таблиц, создание триггеров, создание хранимых процедур и так далее. В WAL попадает всё: обновление таблиц, создание триггеров, создание хранимых процедур и так далее.

View File

@ -12,7 +12,7 @@ date: 2024-03-31
- **Распухание индексов** (bloat) — это проблема увеличения размера индексов со временем, требующая переиндексации. - **Распухание индексов** (bloat) — это проблема увеличения размера индексов со временем, требующая переиндексации.
- [[Создание индекса в PostgreSQL]] - [[Создание индекса в PostgreSQL]]
- [[../Частичный индекс]] - [[../Частичный индекс|Частичный индекс]]
- [[Составной индекс в PostgreSQL]] - [[Составной индекс в PostgreSQL]]
**Типы индексов:** **Типы индексов:**
@ -22,6 +22,10 @@ date: 2024-03-31
- [[SP-GiST индекс в PostgreSQL|SP-GiST индекс]] - [[SP-GiST индекс в PostgreSQL|SP-GiST индекс]]
- [[GIN индекс в PostgreSQL|GIN индекс]] - [[GIN индекс в PostgreSQL|GIN индекс]]
- [[BRIN индекс в PostgreSQL|BRIN индекс]] - [[BRIN индекс в PostgreSQL|BRIN индекс]]
**Влияние обновления строки на индекс**
- **Обновление индексированной колонки.** По факту мы добавляем новую запись в индекс, а старую забываем. Старая остается мертвым грузом (bloat), индекс распухает, его нужно убрать vacuum.
- **Обновление не индексированной колонки.** Если строка в таблице остается на той же [[../DB page|странице бд]], то есть было место на странице, то индекс не меняется. Если строка не помещается, то добавляется новая запись в индекс, а старая остается мертвым грузом (bloat), индекс распухает, его нужно убрать vacuum.
*** ***
## Мета информация ## Мета информация
**Область**:: [[../../../meta/zero/00 PostgreSQL|00 PostgreSQL]] **Область**:: [[../../../meta/zero/00 PostgreSQL|00 PostgreSQL]]

View File

@ -26,13 +26,15 @@ EXPLAIN (FORMAT JSON) SELECT * FROM users WHERE id = 20;
> [!NOTE] Analyze > [!NOTE] Analyze
> `EXPLAIN` не выполняет сам запрос, поэтому результаты будут приблизительными. Для более точного анализа можно добавить ключевое слово `ANALYZE`, и тогда `EXPLAIN` также выполнит запрос. > `EXPLAIN` не выполняет сам запрос, поэтому результаты будут приблизительными. Для более точного анализа можно добавить ключевое слово `ANALYZE`, и тогда `EXPLAIN` также выполнит запрос.
## Стоимость выполнения запроса (cost) ## Стоимость выполнения запроса (cost)
PostgreSQL использует условные единицы для обозначения стоимости выполнения запроса — `cost`. Один `cost` примерно соответствует времени, затраченному на извлечение одного блока данных размером 8 килобайт при последовательном сканировании (Seq Scan). PostgreSQL использует условные единицы для обозначения стоимости выполнения запроса — `cost`. Один `cost` примерно соответствует времени, затраченному на извлечение одной [[../DB page|страницы]] при последовательном сканировании (Seq Scan).
Часто используются два значения `cost`: Часто используются два значения `cost`:
- **Первое значение**: стоимость до начала получения первых результатов. - **Первое значение**: стоимость до начала получения первых результатов.
- **Второе значение**: полная стоимость выполнения запроса. - **Второе значение**: полная стоимость выполнения запроса.
Если оценочное значение `rows` слишком низкое по сравнению с фактическим количеством строк, это может означать, что статистика таблицы устарела. В таком случае необходимо выполнить `ANALYZE` для обновления статистики и улучшения качества планирования запросов. Если оценочное значение `rows` слишком низкое по сравнению с фактическим количеством строк, это может означать, что статистика таблицы устарела. В таком случае необходимо выполнить `ANALYZE` для обновления статистики и улучшения качества планирования запросов.
Также PostgreSQL умеет считать количество обращений к диску. Для этого нужно добавить опцию `buffres`: `explain (analize, buffres)`. Это не время на чтение.
## Виды проходов по таблице и индексу ## Виды проходов по таблице и индексу
- **Seq Scan**: последовательный просмотр всей таблицы. Это наиболее медленный вариант и обычно нежелателен. Решение — добавить [[../Индекс базы данных|индекс]], чтобы ускорить выборку данных. - **Seq Scan**: последовательный просмотр всей таблицы. Это наиболее медленный вариант и обычно нежелателен. Решение — добавить [[../Индекс базы данных|индекс]], чтобы ускорить выборку данных.
- **Index Scan**: использование [[../Индекс базы данных|индекса]] для просмотра таблицы. - **Index Scan**: использование [[../Индекс базы данных|индекса]] для просмотра таблицы.

View File

@ -5,7 +5,7 @@ tags:
date: 2024-03-31 date: 2024-03-31
linked: linked:
--- ---
[[../Составные индексы в БД|Составные индексы]] в PostgreSQL позволяют ускорить выполнение запросов, в которых используются несколько колонок одновременно. Однако важно учитывать особенности их частичного использования. [[../Составной индекс в БД|Составные индексы]] в PostgreSQL позволяют ускорить выполнение запросов, в которых используются несколько колонок одновременно. Однако важно учитывать особенности их частичного использования.
При выполнении запроса составной индекс может использоваться до первого неравенства включительно. Это означает, что при встрече оператора неравенства (`>`, `<`, `>=`, `<=`) индекс перестает быть эффективным для последующих колонок. При выполнении запроса составной индекс может использоваться до первого неравенства включительно. Это означает, что при встрече оператора неравенства (`>`, `<`, `>=`, `<=`) индекс перестает быть эффективным для последующих колонок.
@ -17,7 +17,7 @@ linked:
*** ***
## Мета информация ## Мета информация
**Область**:: [[../../../meta/zero/00 PostgreSQL|00 PostgreSQL]] **Область**:: [[../../../meta/zero/00 PostgreSQL|00 PostgreSQL]]
**Родитель**:: [[../Составные индексы в БД|Составные индексы в БД]], [[Индекс в PostgreSQL]] **Родитель**:: [[../Составной индекс в БД|Составной индекс в БД]], [[Индекс в PostgreSQL]]
**Источник**:: **Источник**::
**Автор**:: **Автор**::
**Создана**:: **Создана**::

View File

@ -0,0 +1,24 @@
---
aliases:
- таблица
- таблице
tags:
- maturity/🌱
date: 2024-11-04
---
Таблица - это гомогенное множество кортежей.
Таблица разбивается на [[../DB page|страницы]].
***
## Мета информация
**Область**:: [[../../../meta/zero/00 PostgreSQL|00 PostgreSQL]]
**Родитель**::
**Источник**::
**Создана**:: [[2024-11-04]]
**Автор**::
### Дополнительные материалы
-
### Дочерние заметки
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->

View File

@ -48,7 +48,7 @@ date: 2024-10-11
**Какие бывают индексы?** **Какие бывают индексы?**
- **Уникальные и неуникальные.** Уникальные индексы обеспечивают уникальность значений в столбцах. Неуникальные индексы допускают повторяющиеся значения. - **Уникальные и неуникальные.** Уникальные индексы обеспечивают уникальность значений в столбцах. Неуникальные индексы допускают повторяющиеся значения.
- **Простые и составные.** Простые индексы создаются для одного столбца, а [[Составные индексы в БД|составные]] — для нескольких столбцов. - **Простые и составные.** Простые индексы создаются для одного столбца, а [[Составной индекс в БД|составные]] — для нескольких столбцов.
- **Кластерные и некластерные.** Кластерные индексы определяют физическое расположение данных на диске, а некластерные индексы хранят указатели на строки таблицы. - **Кластерные и некластерные.** Кластерные индексы определяют физическое расположение данных на диске, а некластерные индексы хранят указатели на строки таблицы.
**Реализации:** **Реализации:**
@ -67,9 +67,9 @@ date: 2024-10-11
### Дочерние заметки ### Дочерние заметки
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) --> <!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
<!-- SerializedQuery: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) --> <!-- SerializedQuery: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
- [[Индекс в PostgreSQL]]
- [[Индекс в MySQL]] - [[Индекс в MySQL]]
- [[Составные индексы в БД]] - [[Индекс в PostgreSQL]]
- [[Покрывающий индекс]] - [[Покрывающий индекс]]
- [[Составной индекс в БД]]
<!-- SerializedQuery END --> <!-- SerializedQuery END -->

View File

@ -0,0 +1,30 @@
---
aliases:
tags:
- maturity/🌱
- best-practices
date: 2024-11-05
---
Представьте, что вам нужно поддерживать уникальность данных, например, адресов электронной почты в таблице базы данных. Однако в таблице есть строки, [[../Tombstone|помеченные как удаленные]] с помощью поля `deleted_at`, и они также остаются в базе данных. В такой ситуации создание уникального индекса на поле с электронной почтой становится невозможным из-за дублирующихся значений. [[Частичный индекс|Частичный индекс]] решает эту проблему, позволяя включать в индекс только записи, которые не помечены как удаленные.
В PostgreSQL добавление уникального индекса для активных пользователей выглядит так:
```sql
CREATE UNIQUE INDEX users_email_uniq ON users (
email
) WHERE deleted_at IS NULL;
```
В этом случае строки, у которых `deleted_at` не задан, включаются в индекс, а остальные игнорируются, что делает индекс более компактным и эффективным.
***
## Мета информация
**Область**:: [[../../meta/zero/00 Базы Данных|00 Базы Данных]]
**Родитель**::
**Источник**::
**Создана**:: [[2024-11-05]]
**Автор**::
### Дополнительные материалы
-
### Дочерние заметки
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->

View File

@ -0,0 +1,25 @@
---
aliases:
tags:
- maturity/🌱
- hack
date: 2024-11-05
---
Если в таблице много записей с одинаковыми значениями (низкая [[Селективность колонки|селективность]]), и необходимо индексировать только записи с уникальными или более специфичными значениями, то можно использовать проблему низкой селективности для повышения эффективности запросов.
Когда менее селективные поля находятся в начале индекса, на одной [[DB page|странице]] в памяти базы данных группируются записи с одинаковыми значениями по этим полям. Это позволяет при поиске уникального значения считывать меньше [[DB page|страниц]] из памяти, что в некоторых случаях может улучшить производительность.
![[../../meta/files/images/Pasted image 20241105002717.png]]
***
## Мета информация
**Область**:: [[../../meta/zero/00 Базы Данных|00 Базы Данных]]
**Родитель**::
**Источник**::
**Создана**:: [[2024-11-05]]
**Автор**::
### Дополнительные материалы
-
### Дочерние заметки
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->

View File

@ -1,18 +1,17 @@
--- ---
aliases: aliases:
- Составные индексы - Составные индексы
- многоколоночный индекс
tags: tags:
- maturity/🌱 - maturity/🌱
date: 2024-06-16 date: 2024-06-16
--- ---
Составным называется индекс, который включает в себя сразу несколько полей. Он используется для повышения производительности запросов, которые фильтруют данные по нескольким колонкам одновременно. Составной индекс — это индекс, включающий несколько полей, который используется для повышения производительности запросов, фильтрующих данные сразу по нескольким колонкам.
==В составных индексах важен порядок столбцов.== Порядок колонок в индексе влияет на его эффективность, и более [[Селективность колонки|селективные]] поля должны идти первыми, чтобы максимизировать производительность. SQL-запросы также должны следовать этому порядку для оптимального использования индекса. Проще всего представить составной индекс не как последовательность индексов по отдельным колонкам, а как индекс по объединённым значениям этих колонок. Поэтому порядок столбцов в составном индексе имеет значение.== Он влияет на эффективность индекса, и поэтому чаще всего ==наиболее [[Селективность колонки|селективные]] поля следует располагать первыми== для максимальной производительности. ==SQL-запросы также должны учитывать этот порядок== для оптимального использования индекса.
При поиске по составному индексу значения колонок сравниваются по порядку, что делает порядок следования колонок критически важным для эффективности запросов. Однако, есть исключительные ситуации из этого правила:
- [[Использование малоселективных полей для оптимизации чтения страниц]]
> [!WARNING] Количество параметров
> Составной индекс из 2-3 полей обычно считается нормальным и эффективно поддерживаемым. Если количество колонок в индексе превышает три, следует тщательно анализировать его использование, чтобы избежать излишней нагрузки на производительность.
**Преимущества:** **Преимущества:**
- **Оптимизация дискового пространства**: ==Один составной индекс может заменить несколько простых индексов==, что экономит дисковое пространство. - **Оптимизация дискового пространства**: ==Один составной индекс может заменить несколько простых индексов==, что экономит дисковое пространство.
@ -22,6 +21,12 @@ date: 2024-06-16
- **Высокие накладные расходы при обновлении**: Каждый раз при вставке, обновлении или удалении данных, которые попадают в составной индекс, СУБД должна обновлять весь индекс, что может увеличивать время выполнения таких операций. - **Высокие накладные расходы при обновлении**: Каждый раз при вставке, обновлении или удалении данных, которые попадают в составной индекс, СУБД должна обновлять весь индекс, что может увеличивать время выполнения таких операций.
- Старайтесь минимизировать использование неравенств в начале составных индексов, так как это может ограничить их применение для последующих колонок. - Старайтесь минимизировать использование неравенств в начале составных индексов, так как это может ограничить их применение для последующих колонок.
> [!WARNING] Количество параметров
> Составной индекс из 2-3 полей обычно считается нормальным и эффективно поддерживаемым. Если количество колонок в индексе превышает три, следует тщательно анализировать его использование, чтобы избежать излишней нагрузки на производительность.
Создание составного индекса: Создание составного индекса:
```sql ```sql
CREATE INDEX idx_example ON table_name (column_a, column_b); CREATE INDEX idx_example ON table_name (column_a, column_b);

View File

@ -0,0 +1,44 @@
---
aliases:
tags:
- maturity/🌱
- best-practices
date: 2024-11-05
---
Часто в приложениях есть таблицы, которые содержат колонку статуса (`state`). Обычно статус разделяет записи на "обработанные" и "необработанные". Индекс нам часто нужен именно по необработанным данным. Создавая [[Частичный индекс|частичный индекс]] только по необработанным данным, мы можем ускорить выполнение запроса и уменьшить размер индекса.
Возьмем типичную табличку, в которой есть какие-то статусы мы хотим находить данные по этому статусу.
![300](../../meta/files/images/Pasted%20image%2020240331095959.png)
![600](../../meta/files/images/Pasted%20image%2020240331100144.png)
Часто появляется желание сделать индекс по полю статуса:
![600](../../meta/files/images/Снимок%20экрана%202024-03-31%20в%2010.07.02.png)
Но по факту мы индексируем поле, которое имеет небольшую [селективность](../../dev/database/Селективность%20колонки.md). Такой индекс не эффективный.
Хороший вариант в данном случае:
![600](../../meta/files/images/Снимок%20экрана%202024-03-31%20в%2010.13.39.png)
Почти идеальный:
![600](../../meta/files/images/Снимок%20экрана%202024-03-31%20в%2010.15.06.png)
![500](../../meta/files/images/Pasted%20image%2020240331101612.png)
Идеальный. Совмещаем и [[postgresql/Составной индекс в PostgreSQL|составной индекс]] и частичный.
![[../../meta/files/images/Pasted image 20241021225124.png]]
***
## Мета информация
**Область**:: [[../../meta/zero/00 Базы Данных|00 Базы Данных]]
**Родитель**::
**Источник**::
**Создана**:: [[2024-11-05]]
**Автор**::
### Дополнительные материалы
-
### Дочерние заметки
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->

View File

@ -26,46 +26,8 @@ WHERE fk_id IS NOT NULL;
**Когда использовать частичные индексы:** **Когда использовать частичные индексы:**
- Когда необходимо уменьшить размер индекса за счёт исключения ненужных записей, что позволяет сэкономить место на диске и ускорить операции поиска. - Когда необходимо уменьшить размер индекса за счёт исключения ненужных записей, что позволяет сэкономить место на диске и ускорить операции поиска.
- Когда таблица содержит большое количество записей с одинаковыми значениями (низкая [[Селективность колонки|селективность]]), и вам нужно индексировать только те записи, которые имеют уникальные или более специфичные значения. - [[Использование малоселективных полей для оптимизации чтения страниц]]
- В ситуациях, когда индекс нужен для работы с данными, которые соответствуют определённому условию, например, только "необработанные" записи. - [[Таблицы с колонкой статуса]]. В ситуациях, когда индекс нужен для работы с данными, которые соответствуют определённому условию, например, только "необработанные" записи.
## Применение частичных индексов
### Таблицы с колонкой статуса
Часто в приложениях есть таблицы, которые содержат колонку статуса (`state`). Обычно статус разделяет записи на "обработанные" и "необработанные". Индекс нам часто нужен именно по необработанным данным. Создавая частичный индекс только по необработанным данным, мы можем ускорить выполнение запроса и уменьшить размер индекса.
Возьмем типичную табличку, в которой есть какие-то статусы мы хотим находить данные по этому статусу.
![300](../../meta/files/images/Pasted%20image%2020240331095959.png)
![600](../../meta/files/images/Pasted%20image%2020240331100144.png)
Часто появляется желание сделать индекс по полю статуса:
![600](../../meta/files/images/Снимок%20экрана%202024-03-31%20в%2010.07.02.png)
Но по факту мы индексируем поле, которое имеет небольшую [селективность](../../dev/database/Селективность%20колонки.md). Такой индекс не эффективный.
Хороший вариант в данном случае:
![600](../../meta/files/images/Снимок%20экрана%202024-03-31%20в%2010.13.39.png)
Почти идеальный:
![600](../../meta/files/images/Снимок%20экрана%202024-03-31%20в%2010.15.06.png)
![500](../../meta/files/images/Pasted%20image%2020240331101612.png)
Идеальный. Совмещаем и [[postgresql/Составной индекс в PostgreSQL|составной индекс]] и частичный.
![[../../meta/files/images/Pasted image 20241021225124.png]]
### Для мягкого удаления
Представьте, что вам нужно поддерживать уникальность данных, например, адресов электронной почты в таблице базы данных. Однако в таблице есть строки, [[../Tombstone|помеченные как удаленные]] с помощью поля `deleted_at`, и они также остаются в базе данных. В такой ситуации создание уникального индекса на поле с электронной почтой становится невозможным из-за дублирующихся значений. Частичный индекс решает эту проблему, позволяя включать в индекс только записи, которые не помечены как удаленные.
В PostgreSQL добавление уникального индекса для активных пользователей выглядит так:
```sql
CREATE UNIQUE INDEX users_email_uniq ON users (
email
) WHERE deleted_at IS NULL;
```
В этом случае строки, у которых `deleted_at` не задан, включаются в индекс, а остальные игнорируются, что делает индекс более компактным и эффективным.
*** ***
## Мета информация ## Мета информация
**Область**:: [[../../meta/zero/00 PostgreSQL|00 PostgreSQL]] **Область**:: [[../../meta/zero/00 PostgreSQL|00 PostgreSQL]]

View File

@ -12,9 +12,10 @@ date: 2024-01-29
- Узел содержит множество элементов, что позволяет хранить больше данных в одном месте. - Узел содержит множество элементов, что позволяет хранить больше данных в одном месте.
- Каждый узел представляет собой [[../Страница|страничку]] на диске, что снижает издержки на чтение. - Каждый узел представляет собой [[../Страница|страничку]] на диске, что снижает издержки на чтение.
- В каждом узле есть ссылки на следующий и предыдущий узлы (характерно для B+tree). - В каждом узле есть ссылки на следующий и предыдущий узлы (характерно для B+tree).
- В узлах дерева могут храниться сами данные или указатели на данные. - В листьях дерева могут храниться сами данные или указатели на данные, то есть ссылаются на таблицу.
- Элементы в узле отсортированы, что делает поиск более эффективным и позволяет создавать деревья с небольшой высотой, тем самым уменьшая количество обращений к диску. - Элементы в узле отсортированы, что делает поиск более эффективным и позволяет создавать деревья с небольшой высотой, тем самым уменьшая количество обращений к диску.
- Значения в узлах могут быть не уникальными. - Значения в узлах могут быть не уникальными.
- Обычно высота дерева не больше 3-4 уровней.
## Параметр t ## Параметр t
Параметр `t` определяет количество элементов в узле дерева. Параметр `t` определяет количество элементов в узле дерева.
- В каждом узле должно быть не менее `t-1` и не более `2t-1` ключей. Это правило важно для поддержания сбалансированности дерева, так как позволяет равномерно распределять элементы между узлами и поддерживать эффективную высоту дерева, что, в свою очередь, обеспечивает высокую производительность операций поиска. - В каждом узле должно быть не менее `t-1` и не более `2t-1` ключей. Это правило важно для поддержания сбалансированности дерева, так как позволяет равномерно распределять элементы между узлами и поддерживать эффективную высоту дерева, что, в свою очередь, обеспечивает высокую производительность операций поиска.
@ -31,13 +32,23 @@ date: 2024-01-29
- Поиск четных или нечетных чисел. - Поиск четных или нечетных чисел.
- Поиск суффиксов (`LIKE '%c'` — неэффективно). - Поиск суффиксов (`LIKE '%c'` — неэффективно).
## Поиск в B-tree ## Поиск в B-tree
Рассмотрим пример поиска значения `27`.
![](../../../meta/files/images/Pasted%20image%2020240129193115.png)
Значения в узлах могут быть не уникальными. Например, если значение `27` встречается дважды, поиск продолжается, переходя в следующий узел. Чтобы облегчить этот процесс, блоки на одном уровне связаны, создавая связный список.
Алгоритм поиска аналогичен [[Бинарное дерево поиска|бинарному дереву]], но выбор осуществляется из нескольких вариантов, а не из двух. Поиск выполняется за `O(t logt(n))`, но количество обращений к диску — `O(logt(n))`. Алгоритм поиска аналогичен [[Бинарное дерево поиска|бинарному дереву]], но выбор осуществляется из нескольких вариантов, а не из двух. Поиск выполняется за `O(t logt(n))`, но количество обращений к диску — `O(logt(n))`.
Рассмотрим пример поиска значения `5`. Начинаем с корневого блока, он всегда один. 5 больше 1, но меньше 7, поэтому идем в левую часть индекса.
![[../../../meta/files/images/Pasted image 20241104203100.png]]
Видим, что 5 больше чем 4, поэтому идем по ссылке на 4
![[../../../meta/files/images/Pasted image 20241104203423.png]]
И там уже мы находим нашу 5.
![[../../../meta/files/images/Pasted image 20241104203446.png]]
А пятерка в свою очередь указывает на место в таблице, и мы можем достать оттуда данные.
![[../../../meta/files/images/Pasted image 20241104203517.png]]
Значения в узлах могут быть не уникальными. Например, если значение `5` встречается дважды, поиск продолжается, переходя в следующий узел. Чтобы облегчить этот процесс, блоки на одном уровне связаны, создавая связный список.
## Добавление в B-tree ## Добавление в B-tree
Представим, что нужно вставить значение `15` в уже существующее дерево. Представим, что нужно вставить значение `15` в уже существующее дерево.

View File

@ -3,12 +3,11 @@ aliases:
- страницы - страницы
- страниц - страниц
- страничку - страничку
- страницы ОС
- Страница ОС
tags: tags:
- maturity/🌱 - maturity/🌱
date: 2024-09-17 date: 2024-09-17
zero-link:
parents:
linked:
--- ---
Страница это непрерывный блок памяти фиксированного размера. Страница это непрерывный блок памяти фиксированного размера.
@ -39,3 +38,6 @@ linked:
### Дочерние заметки ### Дочерние заметки
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) --> <!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
<!-- SerializedQuery: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->
- [[DB page]]
<!-- SerializedQuery END -->

View File

@ -0,0 +1,37 @@
---
aliases:
tags:
- maturity/🌱
date: 2024-11-04
---
```
L1 cache reference ......................... 0.5 ns
Branch mispredict ............................ 5 ns
L2 cache reference ........................... 7 ns
Mutex lock/unlock ........................... 25 ns
Main memory reference ...................... 100 ns
Compress 1K bytes with Zippy ............. 3,000 ns = 3 µs
Send 2K bytes over 1 Gbps network ....... 20,000 ns = 20 µs
SSD random read ........................ 150,000 ns = 150 µs
Read 1 MB sequentially from memory ..... 250,000 ns = 250 µs
Round trip within same datacenter ...... 500,000 ns = 0.5 ms
Read 1 MB sequentially from SSD* ..... 1,000,000 ns = 1 ms
Disk seek ........................... 10,000,000 ns = 10 ms
Read 1 MB sequentially from disk .... 20,000,000 ns = 20 ms
Send packet CA->Netherlands->CA .... 150,000,000 ns = 150 ms
```
![[../../meta/files/images/Pasted image 20241104204304.png]]
***
## Мета информация
**Область**:: [[../../meta/zero/00 Разработка|00 Разработка]]
**Родитель**::
**Источник**::
**Создана**:: [[2024-11-04]]
**Автор**::
### Дополнительные материалы
-
### Дочерние заметки
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->

View File

@ -0,0 +1,23 @@
---
aliases:
tags:
- maturity/🌱
date: 2024-11-05
---
-
- [[2024-11-05]]. [Владимир Ситников — B-tree индексы в базах данных на примере PostgreSQL - YouTube](https://www.youtube.com/watch?v=mnEU2_cwE_s)
- [[2024-11-05]]. [[../source/lecture/Доклад. Могут ли Virtual threads заменить Webflux|Доклад. Могут ли Virtual threads заменить Webflux]]
- [[2024-11-05]]. [[../source/lecture/Доклад. Индексы в PostgreSQL. Как понять, что создавать|Доклад. Индексы в PostgreSQL. Как понять, что создавать]]
***
## Мета информация
**Область**:: [[../source/00 Источники|00 Источники]]
**Родитель**::
**Источник**::
**Создана**:: [[2024-11-05]]
**Автор**::
### Дополнительные материалы
-
### Дочерние заметки
<!-- QueryToSerialize: LIST FROM [[]] WHERE contains(Родитель, this.file.link) or contains(parents, this.file.link) -->

View File

@ -79,6 +79,7 @@ enableToc: false
**По типу контента:** **По типу контента:**
#content/opinion - Мое субъективное мнение по какой-то теме, по какому-то вопросу. #content/opinion - Мое субъективное мнение по какой-то теме, по какому-то вопросу.
#content/problem - Заметки, которые появились для решения проблем, с которыми я сталкивался.
#content/checklist - Различные полезные чек-листы. #content/checklist - Различные полезные чек-листы.
#type/archive - Архивные заметки. Их обновление не планируется, так как тема потеряла для меня интерес. #type/archive - Архивные заметки. Их обновление не планируется, так как тема потеряла для меня интерес.

Binary file not shown.

After

Width:  |  Height:  |  Size: 614 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 601 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 637 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 668 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 716 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 810 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

View File

@ -0,0 +1 @@
f7acfd614fc477ebff10b74de2d716ed

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

View File

@ -0,0 +1 @@
933b38087b1601e6864908001b041df5

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

View File

@ -0,0 +1 @@
e82618e260f128c6cd048561af961e44

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

View File

@ -0,0 +1 @@
611a31d49324aab65ef65af0d5710ad7

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

View File

@ -0,0 +1 @@
bf46eb6f9a60ee2907f1030ceb9ce2cf

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -0,0 +1 @@
035fd400699ca217a05fbe1e517d12a8

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 KiB

View File

@ -0,0 +1 @@
b46e120ce165d4f7a8ea5df8c60a4d31

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

View File

@ -0,0 +1 @@
f7acfd614fc477ebff10b74de2d716ed

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

View File

@ -0,0 +1 @@
933b38087b1601e6864908001b041df5

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

View File

@ -0,0 +1 @@
e82618e260f128c6cd048561af961e44

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

View File

@ -0,0 +1 @@
611a31d49324aab65ef65af0d5710ad7

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

View File

@ -0,0 +1 @@
bf46eb6f9a60ee2907f1030ceb9ce2cf

View File

@ -0,0 +1 @@
035fd400699ca217a05fbe1e517d12a8

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

View File

@ -0,0 +1 @@
b46e120ce165d4f7a8ea5df8c60a4d31

View File

@ -19,6 +19,7 @@ title: PostgreSQL
- Изменение данных не заменяет строчку физически в памяти, а добавляет новую версию строки. Устаревшие строки через какое-то время помечаются и в них пишутся новые данные. - Изменение данных не заменяет строчку физически в памяти, а добавляет новую версию строки. Устаревшие строки через какое-то время помечаются и в них пишутся новые данные.
- Если транзакции нужно выполнить операцию с данными, с которыми работает другая транзакция, то она может встать в очередь. - Если транзакции нужно выполнить операцию с данными, с которыми работает другая транзакция, то она может встать в очередь.
- В логи попадают не все запросы. Это настраивается конфигурационными параметрами. Если логировать все запросы, то просядет производительность. - В логи попадают не все запросы. Это настраивается конфигурационными параметрами. Если логировать все запросы, то просядет производительность.
- Типичный размер [[../../dev/database/DB page|страницы]] 8 килобайт. На страницу помещается ~ 100 записей.
## Дополнительные материалы ## Дополнительные материалы
- [pg_utils](../../dev/database/postgresql/pg_utils.md) - [pg_utils](../../dev/database/postgresql/pg_utils.md)

View File

@ -35,7 +35,7 @@ linked:
## Заметки ## Заметки
- Классические СУБД хранят данные в двух местах: на диске и в памяти. - Классические СУБД хранят данные в двух местах: на диске и в памяти.
- [[../../dev/fundamental/Страница|Страница]] модифицируется сначала в оперативной памяти, потом попадает на диск. - [[../../dev/database/DB page|Страница БД]] модифицируется сначала в оперативной памяти, потом попадает на диск.
- ![](Pasted%20image%2020240531082744.png) - ![](Pasted%20image%2020240531082744.png)
- Часто думают, что реляционная таблица — это массив. Некоторые даже думают, что это двумерный массив. На самом деле, это гораздо более сложная штука. Это мультимножество набор определенного сорта кортежей, над которым не задано порядка. В SQL-таблице нет порядка. Это важно. И, как результат, когда вы делаете SELECT* из БД (просканировать все записи), результат выполнения запроса может меняться строчки могут быть в одном порядке, а могут и в другом. Про это нужно помнить. - Часто думают, что реляционная таблица — это массив. Некоторые даже думают, что это двумерный массив. На самом деле, это гораздо более сложная штука. Это мультимножество набор определенного сорта кортежей, над которым не задано порядка. В SQL-таблице нет порядка. Это важно. И, как результат, когда вы делаете SELECT* из БД (просканировать все записи), результат выполнения запроса может меняться строчки могут быть в одном порядке, а могут и в другом. Про это нужно помнить.
- Профиль нагрузки на реляционную базу данных выглядит следующим образом: 80% запросов это чтение, 20% запросов это запись. Если запросов на запись больше, то возможно реляционная база данных вам не подходит. - Профиль нагрузки на реляционную базу данных выглядит следующим образом: 80% запросов это чтение, 20% запросов это запись. Если запросов на запись больше, то возможно реляционная база данных вам не подходит.

View File

@ -4,11 +4,15 @@ tags:
date: 2024-10-02 date: 2024-10-02
--- ---
Здесь собраны ссылки на заметки, в которых я анализирую прочитанный/просмотренный материал. Здесь собраны ссылки на заметки, в которых я анализирую прочитанный/просмотренный материал.
- [[../dev/Посмотренные доклады по разработке|Посмотренные доклады по разработке]]
-
## Доклады ## Доклады
<!-- QueryToSerialize: LIST FROM #type/source/lecture SORT Создана DESC --> <!-- QueryToSerialize: LIST FROM #type/source/lecture SORT Создана DESC -->
<!-- SerializedQuery: LIST FROM #type/source/lecture SORT Создана DESC --> <!-- SerializedQuery: LIST FROM #type/source/lecture SORT Создана DESC -->
- [[Доклад. Могут ли Virtual threads заменить Webflux]] - [[Доклад. Могут ли Virtual threads заменить Webflux]]
- [[Доклад]] - [[Доклад]]
- [[Доклад. Индексы в PostgreSQL. Как понять, что создавать]]
<!-- SerializedQuery END --> <!-- SerializedQuery END -->
## Статьи ## Статьи
<!-- QueryToSerialize: LIST FROM #type/source/article SORT Создана DESC --> <!-- QueryToSerialize: LIST FROM #type/source/article SORT Создана DESC -->